Index: Source/core/platform/graphics/GraphicsContext.cpp |
diff --git a/Source/core/platform/graphics/GraphicsContext.cpp b/Source/core/platform/graphics/GraphicsContext.cpp |
deleted file mode 100644 |
index 0be006cf772c58b71df2af4ebfaa4a6f5643aff0..0000000000000000000000000000000000000000 |
--- a/Source/core/platform/graphics/GraphicsContext.cpp |
+++ /dev/null |
@@ -1,1974 +0,0 @@ |
-/* |
- * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved. |
- * Copyright (C) 2013 Google Inc. All rights reserved. |
- * |
- * Redistribution and use in source and binary forms, with or without |
- * modification, are permitted provided that the following conditions |
- * are met: |
- * 1. Redistributions of source code must retain the above copyright |
- * notice, this list of conditions and the following disclaimer. |
- * 2. Redistributions in binary form must reproduce the above copyright |
- * notice, this list of conditions and the following disclaimer in the |
- * documentation and/or other materials provided with the distribution. |
- * |
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
- * THE POSSIBILITY OF SUCH DAMAGE. |
- */ |
- |
-#include "config.h" |
-#include "core/platform/graphics/GraphicsContext.h" |
- |
-#include "core/platform/graphics/BitmapImage.h" |
-#include "core/platform/graphics/Gradient.h" |
-#include "platform/geometry/IntRect.h" |
-#include "platform/geometry/RoundedRect.h" |
-#include "platform/graphics/DisplayList.h" |
-#include "platform/graphics/TextRunIterator.h" |
-#include "platform/text/BidiResolver.h" |
-#include "platform/weborigin/KURL.h" |
-#include "third_party/skia/include/core/SkAnnotation.h" |
-#include "third_party/skia/include/core/SkColorFilter.h" |
-#include "third_party/skia/include/core/SkData.h" |
-#include "third_party/skia/include/core/SkPicture.h" |
-#include "third_party/skia/include/core/SkRRect.h" |
-#include "third_party/skia/include/core/SkRefCnt.h" |
-#include "third_party/skia/include/effects/SkBlurMaskFilter.h" |
-#include "third_party/skia/include/effects/SkCornerPathEffect.h" |
-#include "third_party/skia/include/effects/SkLumaColorFilter.h" |
-#include "wtf/Assertions.h" |
-#include "wtf/MathExtras.h" |
- |
-#if OS(MACOSX) |
-#include <ApplicationServices/ApplicationServices.h> |
-#endif |
- |
-using namespace std; |
-using blink::WebBlendMode; |
- |
-namespace WebCore { |
- |
-struct GraphicsContext::DeferredSaveState { |
- DeferredSaveState(unsigned mask, int count) : m_flags(mask), m_restoreCount(count) { } |
- |
- unsigned m_flags; |
- int m_restoreCount; |
-}; |
- |
-struct GraphicsContext::RecordingState { |
- RecordingState(SkCanvas* currentCanvas, const SkMatrix& currentMatrix, PassRefPtr<DisplayList> displayList) |
- : m_savedCanvas(currentCanvas) |
- , m_displayList(displayList) |
- , m_savedMatrix(currentMatrix) |
- { |
- } |
- |
- SkCanvas* m_savedCanvas; |
- RefPtr<DisplayList> m_displayList; |
- const SkMatrix m_savedMatrix; |
-}; |
- |
-GraphicsContext::GraphicsContext(SkCanvas* canvas) |
- : m_canvas(canvas) |
- , m_deferredSaveFlags(0) |
- , m_annotationMode(0) |
-#if !ASSERT_DISABLED |
- , m_annotationCount(0) |
- , m_layerCount(0) |
-#endif |
- , m_trackOpaqueRegion(false) |
- , m_trackTextRegion(false) |
- , m_useHighResMarker(false) |
- , m_updatingControlTints(false) |
- , m_accelerated(false) |
- , m_isCertainlyOpaque(true) |
- , m_printing(false) |
-{ |
- m_stateStack.append(adoptPtr(new GraphicsContextState())); |
- m_state = m_stateStack.last().get(); |
-} |
- |
-GraphicsContext::~GraphicsContext() |
-{ |
- ASSERT(m_stateStack.size() == 1); |
- ASSERT(!m_annotationCount); |
- ASSERT(!m_layerCount); |
- ASSERT(m_recordingStateStack.isEmpty()); |
-} |
- |
-const SkBitmap* GraphicsContext::bitmap() const |
-{ |
- TRACE_EVENT0("skia", "GraphicsContext::bitmap"); |
- return &m_canvas->getDevice()->accessBitmap(false); |
-} |
- |
-const SkBitmap& GraphicsContext::layerBitmap(AccessMode access) const |
-{ |
- return m_canvas->getTopDevice()->accessBitmap(access == ReadWrite); |
-} |
- |
-SkBaseDevice* GraphicsContext::createCompatibleDevice(const IntSize& size, bool hasAlpha) const |
-{ |
- if (paintingDisabled()) |
- return 0; |
- |
- return m_canvas->createCompatibleDevice(SkBitmap::kARGB_8888_Config, size.width(), size.height(), !hasAlpha); |
-} |
- |
-void GraphicsContext::save() |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- m_stateStack.append(m_state->clone()); |
- m_state = m_stateStack.last().get(); |
- |
- m_saveStateStack.append(DeferredSaveState(m_deferredSaveFlags, m_canvas->getSaveCount())); |
- m_deferredSaveFlags |= SkCanvas::kMatrixClip_SaveFlag; |
-} |
- |
-void GraphicsContext::restore() |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- if (m_stateStack.size() == 1) { |
- WTF_LOG_ERROR("ERROR void GraphicsContext::restore() stack is empty"); |
- return; |
- } |
- |
- m_stateStack.removeLast(); |
- m_state = m_stateStack.last().get(); |
- |
- DeferredSaveState savedState = m_saveStateStack.last(); |
- m_saveStateStack.removeLast(); |
- m_deferredSaveFlags = savedState.m_flags; |
- m_canvas->restoreToCount(savedState.m_restoreCount); |
-} |
- |
-void GraphicsContext::saveLayer(const SkRect* bounds, const SkPaint* paint, SkCanvas::SaveFlags saveFlags) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- realizeSave(SkCanvas::kMatrixClip_SaveFlag); |
- |
- m_canvas->saveLayer(bounds, paint, saveFlags); |
- if (bounds) |
- m_canvas->clipRect(*bounds); |
- if (m_trackOpaqueRegion) |
- m_opaqueRegion.pushCanvasLayer(paint); |
-} |
- |
-void GraphicsContext::restoreLayer() |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- m_canvas->restore(); |
- if (m_trackOpaqueRegion) |
- m_opaqueRegion.popCanvasLayer(this); |
-} |
- |
-void GraphicsContext::beginAnnotation(const GraphicsContextAnnotation& annotation) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- canvas()->beginCommentGroup("GraphicsContextAnnotation"); |
- |
- AnnotationList annotations; |
- annotation.asAnnotationList(annotations); |
- |
- AnnotationList::const_iterator end = annotations.end(); |
- for (AnnotationList::const_iterator it = annotations.begin(); it != end; ++it) |
- canvas()->addComment(it->first, it->second.ascii().data()); |
- |
-#if !ASSERT_DISABLED |
- ++m_annotationCount; |
-#endif |
-} |
- |
-void GraphicsContext::endAnnotation() |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- canvas()->endCommentGroup(); |
- |
- ASSERT(m_annotationCount > 0); |
-#if !ASSERT_DISABLED |
- --m_annotationCount; |
-#endif |
-} |
- |
-void GraphicsContext::setStrokeColor(const Color& color) |
-{ |
- m_state->m_strokeData.setColor(color); |
- m_state->m_strokeData.clearGradient(); |
- m_state->m_strokeData.clearPattern(); |
-} |
- |
-void GraphicsContext::setStrokePattern(PassRefPtr<Pattern> pattern) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- ASSERT(pattern); |
- if (!pattern) { |
- setStrokeColor(Color::black); |
- return; |
- } |
- m_state->m_strokeData.clearGradient(); |
- m_state->m_strokeData.setPattern(pattern); |
-} |
- |
-void GraphicsContext::setStrokeGradient(PassRefPtr<Gradient> gradient) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- ASSERT(gradient); |
- if (!gradient) { |
- setStrokeColor(Color::black); |
- return; |
- } |
- m_state->m_strokeData.setGradient(gradient); |
- m_state->m_strokeData.clearPattern(); |
-} |
- |
-void GraphicsContext::setFillColor(const Color& color) |
-{ |
- m_state->m_fillColor = color; |
- m_state->m_fillGradient.clear(); |
- m_state->m_fillPattern.clear(); |
-} |
- |
-void GraphicsContext::setFillPattern(PassRefPtr<Pattern> pattern) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- ASSERT(pattern); |
- if (!pattern) { |
- setFillColor(Color::black); |
- return; |
- } |
- m_state->m_fillGradient.clear(); |
- m_state->m_fillPattern = pattern; |
-} |
- |
-void GraphicsContext::setFillGradient(PassRefPtr<Gradient> gradient) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- ASSERT(gradient); |
- if (!gradient) { |
- setFillColor(Color::black); |
- return; |
- } |
- m_state->m_fillGradient = gradient; |
- m_state->m_fillPattern.clear(); |
-} |
- |
-void GraphicsContext::setShadow(const FloatSize& offset, float blur, const Color& color, |
- DrawLooper::ShadowTransformMode shadowTransformMode, |
- DrawLooper::ShadowAlphaMode shadowAlphaMode) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- if (!color.isValid() || !color.alpha() || (!offset.width() && !offset.height() && !blur)) { |
- clearShadow(); |
- return; |
- } |
- |
- DrawLooper drawLooper; |
- drawLooper.addShadow(offset, blur, color, shadowTransformMode, shadowAlphaMode); |
- drawLooper.addUnmodifiedContent(); |
- setDrawLooper(drawLooper); |
-} |
- |
-void GraphicsContext::setDrawLooper(const DrawLooper& drawLooper) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- m_state->m_looper = drawLooper.skDrawLooper(); |
-} |
- |
-void GraphicsContext::clearDrawLooper() |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- m_state->m_looper.clear(); |
-} |
- |
-bool GraphicsContext::hasShadow() const |
-{ |
- return !!m_state->m_looper; |
-} |
- |
-int GraphicsContext::getNormalizedAlpha() const |
-{ |
- int alpha = roundf(m_state->m_alpha * 256); |
- if (alpha > 255) |
- alpha = 255; |
- else if (alpha < 0) |
- alpha = 0; |
- return alpha; |
-} |
- |
-bool GraphicsContext::getClipBounds(SkRect* bounds) const |
-{ |
- if (paintingDisabled()) |
- return false; |
- return m_canvas->getClipBounds(bounds); |
-} |
- |
-bool GraphicsContext::getTransformedClipBounds(FloatRect* bounds) const |
-{ |
- if (paintingDisabled()) |
- return false; |
- SkIRect skIBounds; |
- if (!m_canvas->getClipDeviceBounds(&skIBounds)) |
- return false; |
- SkRect skBounds = SkRect::MakeFromIRect(skIBounds); |
- *bounds = FloatRect(skBounds); |
- return true; |
-} |
- |
-SkMatrix GraphicsContext::getTotalMatrix() const |
-{ |
- if (paintingDisabled()) |
- return SkMatrix::I(); |
- |
- if (!isRecording()) |
- return m_canvas->getTotalMatrix(); |
- |
- const RecordingState& recordingState = m_recordingStateStack.last(); |
- SkMatrix totalMatrix = recordingState.m_savedMatrix; |
- totalMatrix.preConcat(m_canvas->getTotalMatrix()); |
- |
- return totalMatrix; |
-} |
- |
-bool GraphicsContext::isPrintingDevice() const |
-{ |
- if (paintingDisabled()) |
- return false; |
- return m_canvas->getTopDevice()->getDeviceCapabilities() & SkBaseDevice::kVector_Capability; |
-} |
- |
-void GraphicsContext::adjustTextRenderMode(SkPaint* paint) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- if (!paint->isLCDRenderText()) |
- return; |
- |
- paint->setLCDRenderText(couldUseLCDRenderedText()); |
-} |
- |
-bool GraphicsContext::couldUseLCDRenderedText() |
-{ |
- // Our layers only have a single alpha channel. This means that subpixel |
- // rendered text cannot be composited correctly when the layer is |
- // collapsed. Therefore, subpixel text is disabled when we are drawing |
- // onto a layer. |
- if (paintingDisabled() || isDrawingToLayer() || !isCertainlyOpaque()) |
- return false; |
- |
- return shouldSmoothFonts(); |
-} |
- |
-void GraphicsContext::setCompositeOperation(CompositeOperator compositeOperation, WebBlendMode blendMode) |
-{ |
- m_state->m_compositeOperator = compositeOperation; |
- m_state->m_blendMode = blendMode; |
- m_state->m_xferMode = WebCoreCompositeToSkiaComposite(compositeOperation, blendMode); |
-} |
- |
-SkColorFilter* GraphicsContext::colorFilter() |
-{ |
- return m_state->m_colorFilter.get(); |
-} |
- |
-void GraphicsContext::setColorFilter(ColorFilter colorFilter) |
-{ |
- // We only support one active color filter at the moment. If (when) this becomes a problem, |
- // we should switch to using color filter chains (Skia work in progress). |
- ASSERT(!m_state->m_colorFilter); |
- m_state->m_colorFilter = WebCoreColorFilterToSkiaColorFilter(colorFilter); |
-} |
- |
-bool GraphicsContext::readPixels(SkBitmap* bitmap, int x, int y, SkCanvas::Config8888 config8888) |
-{ |
- if (paintingDisabled()) |
- return false; |
- |
- return m_canvas->readPixels(bitmap, x, y, config8888); |
-} |
- |
-void GraphicsContext::setMatrix(const SkMatrix& matrix) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- realizeSave(SkCanvas::kMatrix_SaveFlag); |
- |
- m_canvas->setMatrix(matrix); |
-} |
- |
-bool GraphicsContext::concat(const SkMatrix& matrix) |
-{ |
- if (paintingDisabled()) |
- return false; |
- |
- realizeSave(SkCanvas::kMatrix_SaveFlag); |
- |
- return m_canvas->concat(matrix); |
-} |
- |
-void GraphicsContext::beginTransparencyLayer(float opacity, const FloatRect* bounds) |
-{ |
- beginLayer(opacity, m_state->m_compositeOperator, bounds); |
-} |
- |
-void GraphicsContext::beginLayer(float opacity, CompositeOperator op, const FloatRect* bounds, ColorFilter colorFilter) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- // We need the "alpha" layer flag here because the base layer is opaque |
- // (the surface of the page) but layers on top may have transparent parts. |
- // Without explicitly setting the alpha flag, the layer will inherit the |
- // opaque setting of the base and some things won't work properly. |
- SkCanvas::SaveFlags saveFlags = static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag); |
- |
- SkPaint layerPaint; |
- layerPaint.setAlpha(static_cast<unsigned char>(opacity * 255)); |
- layerPaint.setXfermode(WebCoreCompositeToSkiaComposite(op, m_state->m_blendMode).get()); |
- layerPaint.setColorFilter(WebCoreColorFilterToSkiaColorFilter(colorFilter).get()); |
- |
- if (bounds) { |
- SkRect skBounds = WebCoreFloatRectToSKRect(*bounds); |
- saveLayer(&skBounds, &layerPaint, saveFlags); |
- } else { |
- saveLayer(0, &layerPaint, saveFlags); |
- } |
- |
-#if !ASSERT_DISABLED |
- ++m_layerCount; |
-#endif |
-} |
- |
-void GraphicsContext::endLayer() |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- restoreLayer(); |
- |
- ASSERT(m_layerCount > 0); |
-#if !ASSERT_DISABLED |
- --m_layerCount; |
-#endif |
-} |
- |
-void GraphicsContext::beginRecording(const FloatRect& bounds) |
-{ |
- RefPtr<DisplayList> displayList = adoptRef(new DisplayList(bounds)); |
- |
- SkCanvas* savedCanvas = m_canvas; |
- SkMatrix savedMatrix = getTotalMatrix(); |
- |
- IntRect recordingRect = enclosingIntRect(bounds); |
- m_canvas = displayList->picture()->beginRecording(recordingRect.width(), recordingRect.height(), |
- SkPicture::kUsePathBoundsForClip_RecordingFlag); |
- |
- // We want the bounds offset mapped to (0, 0), such that the display list content |
- // is fully contained within the SkPictureRecord's bounds. |
- if (!toFloatSize(bounds.location()).isZero()) { |
- m_canvas->translate(-bounds.x(), -bounds.y()); |
- // To avoid applying the offset repeatedly in getTotalMatrix(), we pre-apply it here. |
- savedMatrix.preTranslate(bounds.x(), bounds.y()); |
- } |
- |
- m_recordingStateStack.append(RecordingState(savedCanvas, savedMatrix, displayList)); |
-} |
- |
-PassRefPtr<DisplayList> GraphicsContext::endRecording() |
-{ |
- ASSERT(!m_recordingStateStack.isEmpty()); |
- |
- RecordingState recording = m_recordingStateStack.last(); |
- ASSERT(recording.m_displayList->picture()->getRecordingCanvas()); |
- recording.m_displayList->picture()->endRecording(); |
- |
- m_recordingStateStack.removeLast(); |
- m_canvas = recording.m_savedCanvas; |
- |
- return recording.m_displayList.release(); |
-} |
- |
-bool GraphicsContext::isRecording() const |
-{ |
- return !m_recordingStateStack.isEmpty(); |
-} |
- |
-void GraphicsContext::drawDisplayList(DisplayList* displayList) |
-{ |
- ASSERT(!displayList->picture()->getRecordingCanvas()); |
- |
- if (paintingDisabled() || !displayList) |
- return; |
- |
- realizeSave(SkCanvas::kMatrixClip_SaveFlag); |
- |
- const FloatRect& bounds = displayList->bounds(); |
- if (bounds.x() || bounds.y()) |
- m_canvas->translate(bounds.x(), bounds.y()); |
- |
- m_canvas->drawPicture(*displayList->picture()); |
- |
- if (bounds.x() || bounds.y()) |
- m_canvas->translate(-bounds.x(), -bounds.y()); |
-} |
- |
-void GraphicsContext::setupPaintForFilling(SkPaint* paint) const |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- setupPaintCommon(paint); |
- |
- setupShader(paint, m_state->m_fillGradient.get(), m_state->m_fillPattern.get(), m_state->m_fillColor.rgb()); |
-} |
- |
-float GraphicsContext::setupPaintForStroking(SkPaint* paint, int length) const |
-{ |
- if (paintingDisabled()) |
- return 0.0f; |
- |
- setupPaintCommon(paint); |
- |
- setupShader(paint, m_state->m_strokeData.gradient(), m_state->m_strokeData.pattern(), |
- m_state->m_strokeData.color().rgb()); |
- |
- return m_state->m_strokeData.setupPaint(paint, length); |
-} |
- |
-void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- if (numPoints <= 1) |
- return; |
- |
- SkPath path; |
- setPathFromConvexPoints(&path, numPoints, points); |
- |
- SkPaint paint; |
- setupPaintForFilling(&paint); |
- paint.setAntiAlias(shouldAntialias); |
- drawPath(path, paint); |
- |
- if (strokeStyle() != NoStroke) { |
- paint.reset(); |
- setupPaintForStroking(&paint); |
- drawPath(path, paint); |
- } |
-} |
- |
-// This method is only used to draw the little circles used in lists. |
-void GraphicsContext::drawEllipse(const IntRect& elipseRect) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- SkRect rect = elipseRect; |
- SkPaint paint; |
- setupPaintForFilling(&paint); |
- drawOval(rect, paint); |
- |
- if (strokeStyle() != NoStroke) { |
- paint.reset(); |
- setupPaintForStroking(&paint); |
- drawOval(rect, paint); |
- } |
-} |
- |
-void GraphicsContext::drawFocusRing(const Path& focusRingPath, int width, int offset, const Color& color) |
-{ |
- // FIXME: Implement support for offset. |
- UNUSED_PARAM(offset); |
- |
- if (paintingDisabled()) |
- return; |
- |
- SkPaint paint; |
- paint.setAntiAlias(true); |
- paint.setStyle(SkPaint::kStroke_Style); |
- paint.setColor(color.rgb()); |
- |
- drawOuterPath(focusRingPath.skPath(), paint, width); |
- drawInnerPath(focusRingPath.skPath(), paint, width); |
-} |
- |
-void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- unsigned rectCount = rects.size(); |
- if (!rectCount) |
- return; |
- |
- SkRegion focusRingRegion; |
- const int focusRingOutset = getFocusRingOutset(offset); |
- for (unsigned i = 0; i < rectCount; i++) { |
- SkIRect r = rects[i]; |
- r.inset(-focusRingOutset, -focusRingOutset); |
- focusRingRegion.op(r, SkRegion::kUnion_Op); |
- } |
- |
- SkPath path; |
- SkPaint paint; |
- paint.setAntiAlias(true); |
- paint.setStyle(SkPaint::kStroke_Style); |
- |
- paint.setColor(color.rgb()); |
- focusRingRegion.getBoundaryPath(&path); |
- drawOuterPath(path, paint, width); |
- drawInnerPath(path, paint, width); |
-} |
- |
-static inline IntRect areaCastingShadowInHole(const IntRect& holeRect, int shadowBlur, int shadowSpread, const IntSize& shadowOffset) |
-{ |
- IntRect bounds(holeRect); |
- |
- bounds.inflate(shadowBlur); |
- |
- if (shadowSpread < 0) |
- bounds.inflate(-shadowSpread); |
- |
- IntRect offsetBounds = bounds; |
- offsetBounds.move(-shadowOffset); |
- return unionRect(bounds, offsetBounds); |
-} |
- |
-void GraphicsContext::drawInnerShadow(const RoundedRect& rect, const Color& shadowColor, const IntSize shadowOffset, int shadowBlur, int shadowSpread, Edges clippedEdges) |
-{ |
- IntRect holeRect(rect.rect()); |
- holeRect.inflate(-shadowSpread); |
- |
- if (holeRect.isEmpty()) { |
- if (rect.isRounded()) |
- fillRoundedRect(rect, shadowColor); |
- else |
- fillRect(rect.rect(), shadowColor); |
- return; |
- } |
- |
- if (clippedEdges & LeftEdge) { |
- holeRect.move(-max(shadowOffset.width(), 0) - shadowBlur, 0); |
- holeRect.setWidth(holeRect.width() + max(shadowOffset.width(), 0) + shadowBlur); |
- } |
- if (clippedEdges & TopEdge) { |
- holeRect.move(0, -max(shadowOffset.height(), 0) - shadowBlur); |
- holeRect.setHeight(holeRect.height() + max(shadowOffset.height(), 0) + shadowBlur); |
- } |
- if (clippedEdges & RightEdge) |
- holeRect.setWidth(holeRect.width() - min(shadowOffset.width(), 0) + shadowBlur); |
- if (clippedEdges & BottomEdge) |
- holeRect.setHeight(holeRect.height() - min(shadowOffset.height(), 0) + shadowBlur); |
- |
- Color fillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), 255); |
- |
- IntRect outerRect = areaCastingShadowInHole(rect.rect(), shadowBlur, shadowSpread, shadowOffset); |
- RoundedRect roundedHole(holeRect, rect.radii()); |
- |
- save(); |
- if (rect.isRounded()) { |
- Path path; |
- path.addRoundedRect(rect); |
- clipPath(path); |
- roundedHole.shrinkRadii(shadowSpread); |
- } else { |
- clip(rect.rect()); |
- } |
- |
- DrawLooper drawLooper; |
- drawLooper.addShadow(shadowOffset, shadowBlur, shadowColor, |
- DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowIgnoresAlpha); |
- setDrawLooper(drawLooper); |
- fillRectWithRoundedHole(outerRect, roundedHole, fillColor); |
- restore(); |
- clearDrawLooper(); |
-} |
- |
-// This is only used to draw borders. |
-void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- StrokeStyle penStyle = strokeStyle(); |
- if (penStyle == NoStroke) |
- return; |
- |
- SkPaint paint; |
- FloatPoint p1 = point1; |
- FloatPoint p2 = point2; |
- bool isVerticalLine = (p1.x() == p2.x()); |
- int width = roundf(strokeThickness()); |
- |
- // We know these are vertical or horizontal lines, so the length will just |
- // be the sum of the displacement component vectors give or take 1 - |
- // probably worth the speed up of no square root, which also won't be exact. |
- FloatSize disp = p2 - p1; |
- int length = SkScalarRound(disp.width() + disp.height()); |
- setupPaintForStroking(&paint, length); |
- |
- 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(p1.x(), p1.y(), p1.x() + width, p1.y() + width); |
- r2.set(p2.x(), p2.y(), p2.x() + width, p2.y() + 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()); |
- drawRect(r1, fillPaint); |
- drawRect(r2, fillPaint); |
- } |
- |
- adjustLineToPixelBoundaries(p1, p2, width, penStyle); |
- SkPoint pts[2] = { (SkPoint)p1, (SkPoint)p2 }; |
- |
- m_canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts, paint); |
- |
- if (m_trackOpaqueRegion) |
- m_opaqueRegion.didDrawPoints(this, SkCanvas::kLines_PointMode, 2, pts, paint); |
-} |
- |
-void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float width, DocumentMarkerLineStyle style) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- int deviceScaleFactor = m_useHighResMarker ? 2 : 1; |
- |
- // Create the pattern we'll use to draw the underline. |
- int index = style == DocumentMarkerGrammarLineStyle ? 1 : 0; |
- static SkBitmap* misspellBitmap1x[2] = { 0, 0 }; |
- static SkBitmap* misspellBitmap2x[2] = { 0, 0 }; |
- SkBitmap** misspellBitmap = deviceScaleFactor == 2 ? misspellBitmap2x : misspellBitmap1x; |
- if (!misspellBitmap[index]) { |
-#if OS(MACOSX) |
- // Match the artwork used by the Mac. |
- const int rowPixels = 4 * deviceScaleFactor; |
- const int colPixels = 3 * deviceScaleFactor; |
- misspellBitmap[index] = new SkBitmap; |
- misspellBitmap[index]->setConfig(SkBitmap::kARGB_8888_Config, |
- rowPixels, colPixels); |
- misspellBitmap[index]->allocPixels(); |
- |
- misspellBitmap[index]->eraseARGB(0, 0, 0, 0); |
- const uint32_t transparentColor = 0x00000000; |
- |
- if (deviceScaleFactor == 1) { |
- const uint32_t colors[2][6] = { |
- { 0x2a2a0600, 0x57571000, 0xa8a81b00, 0xbfbf1f00, 0x70701200, 0xe0e02400 }, |
- { 0x2a0f0f0f, 0x571e1e1e, 0xa83d3d3d, 0xbf454545, 0x70282828, 0xe0515151 } |
- }; |
- |
- // Pattern: a b a a b a |
- // c d c c d c |
- // e f e e f e |
- for (int x = 0; x < colPixels; ++x) { |
- uint32_t* row = misspellBitmap[index]->getAddr32(0, x); |
- row[0] = colors[index][x * 2]; |
- row[1] = colors[index][x * 2 + 1]; |
- row[2] = colors[index][x * 2]; |
- row[3] = transparentColor; |
- } |
- } else if (deviceScaleFactor == 2) { |
- const uint32_t colors[2][18] = { |
- { 0x0a090101, 0x33320806, 0x55540f0a, 0x37360906, 0x6e6c120c, 0x6e6c120c, 0x7674140d, 0x8d8b1810, 0x8d8b1810, |
- 0x96941a11, 0xb3b01f15, 0xb3b01f15, 0x6d6b130c, 0xd9d62619, 0xd9d62619, 0x19180402, 0x7c7a150e, 0xcecb2418 }, |
- { 0x0a020202, 0x33141414, 0x55232323, 0x37161616, 0x6e2e2e2e, 0x6e2e2e2e, 0x76313131, 0x8d3a3a3a, 0x8d3a3a3a, |
- 0x963e3e3e, 0xb34b4b4b, 0xb34b4b4b, 0x6d2d2d2d, 0xd95b5b5b, 0xd95b5b5b, 0x19090909, 0x7c343434, 0xce575757 } |
- }; |
- |
- // Pattern: a b c c b a |
- // d e f f e d |
- // g h j j h g |
- // k l m m l k |
- // n o p p o n |
- // q r s s r q |
- for (int x = 0; x < colPixels; ++x) { |
- uint32_t* row = misspellBitmap[index]->getAddr32(0, x); |
- row[0] = colors[index][x * 3]; |
- row[1] = colors[index][x * 3 + 1]; |
- row[2] = colors[index][x * 3 + 2]; |
- row[3] = colors[index][x * 3 + 2]; |
- row[4] = colors[index][x * 3 + 1]; |
- row[5] = colors[index][x * 3]; |
- row[6] = transparentColor; |
- row[7] = transparentColor; |
- } |
- } else |
- ASSERT_NOT_REACHED(); |
-#else |
- // We use a 2-pixel-high misspelling indicator because that seems to be |
- // what WebKit is designed for, and how much room there is in a typical |
- // page for it. |
- const int rowPixels = 32 * deviceScaleFactor; // Must be multiple of 4 for pattern below. |
- const int colPixels = 2 * deviceScaleFactor; |
- misspellBitmap[index] = new SkBitmap; |
- misspellBitmap[index]->setConfig(SkBitmap::kARGB_8888_Config, rowPixels, colPixels); |
- misspellBitmap[index]->allocPixels(); |
- |
- misspellBitmap[index]->eraseARGB(0, 0, 0, 0); |
- if (deviceScaleFactor == 1) |
- draw1xMarker(misspellBitmap[index], index); |
- else if (deviceScaleFactor == 2) |
- draw2xMarker(misspellBitmap[index], index); |
- else |
- ASSERT_NOT_REACHED(); |
-#endif |
- } |
- |
-#if OS(MACOSX) |
- SkScalar originX = WebCoreFloatToSkScalar(pt.x()) * deviceScaleFactor; |
- SkScalar originY = WebCoreFloatToSkScalar(pt.y()) * deviceScaleFactor; |
- |
- // Make sure to draw only complete dots. |
- int rowPixels = misspellBitmap[index]->width(); |
- float widthMod = fmodf(width * deviceScaleFactor, rowPixels); |
- if (rowPixels - widthMod > deviceScaleFactor) |
- width -= widthMod / deviceScaleFactor; |
-#else |
- SkScalar originX = WebCoreFloatToSkScalar(pt.x()); |
- |
- // Offset it vertically by 1 so that there's some space under the text. |
- SkScalar originY = WebCoreFloatToSkScalar(pt.y()) + 1; |
- originX *= deviceScaleFactor; |
- originY *= deviceScaleFactor; |
-#endif |
- |
- RefPtr<SkShader> shader = adoptRef(SkShader::CreateBitmapShader( |
- *misspellBitmap[index], SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode)); |
- SkMatrix matrix; |
- matrix.setTranslate(originX, originY); |
- shader->setLocalMatrix(matrix); |
- |
- SkPaint paint; |
- paint.setShader(shader.get()); |
- |
- SkRect rect; |
- rect.set(originX, originY, originX + WebCoreFloatToSkScalar(width) * deviceScaleFactor, originY + SkIntToScalar(misspellBitmap[index]->height())); |
- |
- if (deviceScaleFactor == 2) { |
- save(); |
- scale(FloatSize(0.5, 0.5)); |
- } |
- drawRect(rect, paint); |
- if (deviceScaleFactor == 2) |
- restore(); |
-} |
- |
-void GraphicsContext::drawLineForText(const FloatPoint& pt, float width, bool printing) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- if (width <= 0) |
- return; |
- |
- int thickness = SkMax32(static_cast<int>(strokeThickness()), 1); |
- SkRect r; |
- r.fLeft = WebCoreFloatToSkScalar(pt.x()); |
- // Avoid anti-aliasing lines. Currently, these are always horizontal. |
- // Round to nearest pixel to match text and other content. |
- r.fTop = WebCoreFloatToSkScalar(floorf(pt.y() + 0.5f)); |
- r.fRight = r.fLeft + WebCoreFloatToSkScalar(width); |
- r.fBottom = r.fTop + SkIntToScalar(thickness); |
- |
- SkPaint paint; |
- switch (strokeStyle()) { |
- case NoStroke: |
- case SolidStroke: |
- case DoubleStroke: |
- case WavyStroke: |
- setupPaintForFilling(&paint); |
- break; |
- case DottedStroke: |
- case DashedStroke: |
- setupPaintForStroking(&paint); |
- break; |
- } |
- |
- // Text lines are drawn using the stroke color. |
- paint.setColor(effectiveStrokeColor()); |
- drawRect(r, paint); |
-} |
- |
-// Draws a filled rectangle with a stroked border. |
-void GraphicsContext::drawRect(const IntRect& rect) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- ASSERT(!rect.isEmpty()); |
- if (rect.isEmpty()) |
- return; |
- |
- SkRect skRect = rect; |
- SkPaint paint; |
- int fillcolorNotTransparent = m_state->m_fillColor.rgb() & 0xFF000000; |
- if (fillcolorNotTransparent) { |
- setupPaintForFilling(&paint); |
- drawRect(skRect, paint); |
- } |
- |
- if (m_state->m_strokeData.style() != NoStroke && (m_state->m_strokeData.color().rgb() & 0xFF000000)) { |
- // We do a fill of four rects to simulate the stroke of a border. |
- paint.reset(); |
- setupPaintForFilling(&paint); |
- // need to jam in the strokeColor |
- paint.setColor(this->effectiveStrokeColor()); |
- |
- SkRect topBorder = { skRect.fLeft, skRect.fTop, skRect.fRight, skRect.fTop + 1 }; |
- drawRect(topBorder, paint); |
- SkRect bottomBorder = { skRect.fLeft, skRect.fBottom - 1, skRect.fRight, skRect.fBottom }; |
- drawRect(bottomBorder, paint); |
- SkRect leftBorder = { skRect.fLeft, skRect.fTop + 1, skRect.fLeft + 1, skRect.fBottom - 1 }; |
- drawRect(leftBorder, paint); |
- SkRect rightBorder = { skRect.fRight - 1, skRect.fTop + 1, skRect.fRight, skRect.fBottom - 1 }; |
- drawRect(rightBorder, paint); |
- } |
-} |
- |
-void GraphicsContext::drawText(const Font& font, const TextRunPaintInfo& runInfo, const FloatPoint& point) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- font.drawText(this, runInfo, point); |
-} |
- |
-void GraphicsContext::drawEmphasisMarks(const Font& font, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- font.drawEmphasisMarks(this, runInfo, mark, point); |
-} |
- |
-void GraphicsContext::drawBidiText(const Font& font, const TextRunPaintInfo& runInfo, const FloatPoint& point, Font::CustomFontNotReadyAction customFontNotReadyAction) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- // sub-run painting is not supported for Bidi text. |
- const TextRun& run = runInfo.run; |
- ASSERT((runInfo.from == 0) && (runInfo.to == run.length())); |
- BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver; |
- bidiResolver.setStatus(BidiStatus(run.direction(), run.directionalOverride())); |
- bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&run, 0)); |
- |
- // FIXME: This ownership should be reversed. We should pass BidiRunList |
- // to BidiResolver in createBidiRunsForLine. |
- BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs(); |
- bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length())); |
- if (!bidiRuns.runCount()) |
- return; |
- |
- FloatPoint currPoint = point; |
- BidiCharacterRun* bidiRun = bidiRuns.firstRun(); |
- while (bidiRun) { |
- TextRun subrun = run.subRun(bidiRun->start(), bidiRun->stop() - bidiRun->start()); |
- bool isRTL = bidiRun->level() % 2; |
- subrun.setDirection(isRTL ? RTL : LTR); |
- subrun.setDirectionalOverride(bidiRun->dirOverride(false)); |
- |
- TextRunPaintInfo subrunInfo(subrun); |
- subrunInfo.bounds = runInfo.bounds; |
- font.drawText(this, subrunInfo, currPoint, customFontNotReadyAction); |
- |
- bidiRun = bidiRun->next(); |
- // FIXME: Have Font::drawText return the width of what it drew so that we don't have to re-measure here. |
- if (bidiRun) |
- currPoint.move(font.width(subrun), 0); |
- } |
- |
- bidiRuns.deleteRuns(); |
-} |
- |
-void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, const FloatPoint& point, int h, const Color& backgroundColor, int from, int to) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- fillRect(font.selectionRectForText(run, point, h, from, to), backgroundColor); |
-} |
- |
-void GraphicsContext::drawImage(Image* image, const IntPoint& p, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation) |
-{ |
- if (!image) |
- return; |
- drawImage(image, FloatRect(IntRect(p, image->size())), FloatRect(FloatPoint(), FloatSize(image->size())), op, shouldRespectImageOrientation); |
-} |
- |
-void GraphicsContext::drawImage(Image* image, const IntRect& r, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation, bool useLowQualityScale) |
-{ |
- if (!image) |
- return; |
- drawImage(image, FloatRect(r), FloatRect(FloatPoint(), FloatSize(image->size())), op, shouldRespectImageOrientation, useLowQualityScale); |
-} |
- |
-void GraphicsContext::drawImage(Image* image, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation) |
-{ |
- drawImage(image, FloatRect(IntRect(dest, srcRect.size())), FloatRect(srcRect), op, shouldRespectImageOrientation); |
-} |
- |
-void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation, bool useLowQualityScale) |
-{ |
- drawImage(image, dest, src, op, blink::WebBlendModeNormal, shouldRespectImageOrientation, useLowQualityScale); |
-} |
- |
-void GraphicsContext::drawImage(Image* image, const FloatRect& dest) |
-{ |
- if (!image) |
- return; |
- drawImage(image, dest, FloatRect(IntRect(IntPoint(), image->size()))); |
-} |
- |
-void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op, WebBlendMode blendMode, RespectImageOrientationEnum shouldRespectImageOrientation, bool useLowQualityScale) |
-{ if (paintingDisabled() || !image) |
- return; |
- |
- InterpolationQuality previousInterpolationQuality = InterpolationDefault; |
- |
- if (useLowQualityScale) { |
- previousInterpolationQuality = imageInterpolationQuality(); |
- setImageInterpolationQuality(InterpolationLow); |
- } |
- |
- image->draw(this, dest, src, op, blendMode, shouldRespectImageOrientation); |
- |
- if (useLowQualityScale) |
- setImageInterpolationQuality(previousInterpolationQuality); |
-} |
- |
-void GraphicsContext::drawTiledImage(Image* image, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op, bool useLowQualityScale, WebBlendMode blendMode, const IntSize& repeatSpacing) |
-{ |
- if (paintingDisabled() || !image) |
- return; |
- |
- if (useLowQualityScale) { |
- InterpolationQuality previousInterpolationQuality = imageInterpolationQuality(); |
- setImageInterpolationQuality(InterpolationLow); |
- image->drawTiled(this, destRect, srcPoint, tileSize, op, blendMode, repeatSpacing); |
- setImageInterpolationQuality(previousInterpolationQuality); |
- } else { |
- image->drawTiled(this, destRect, srcPoint, tileSize, op, blendMode, repeatSpacing); |
- } |
-} |
- |
-void GraphicsContext::drawTiledImage(Image* image, const IntRect& dest, const IntRect& srcRect, |
- const FloatSize& tileScaleFactor, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op, bool useLowQualityScale) |
-{ |
- if (paintingDisabled() || !image) |
- return; |
- |
- if (hRule == Image::StretchTile && vRule == Image::StretchTile) { |
- // Just do a scale. |
- drawImage(image, dest, srcRect, op); |
- return; |
- } |
- |
- if (useLowQualityScale) { |
- InterpolationQuality previousInterpolationQuality = imageInterpolationQuality(); |
- setImageInterpolationQuality(InterpolationLow); |
- image->drawTiled(this, dest, srcRect, tileScaleFactor, hRule, vRule, op); |
- setImageInterpolationQuality(previousInterpolationQuality); |
- } else { |
- image->drawTiled(this, dest, srcRect, tileScaleFactor, hRule, vRule, op); |
- } |
-} |
- |
-void GraphicsContext::drawImageBuffer(ImageBuffer* image, const IntPoint& p, CompositeOperator op, WebBlendMode blendMode) |
-{ |
- if (!image) |
- return; |
- drawImageBuffer(image, FloatRect(IntRect(p, image->logicalSize())), FloatRect(FloatPoint(), FloatSize(image->logicalSize())), op, blendMode); |
-} |
- |
-void GraphicsContext::drawImageBuffer(ImageBuffer* image, const IntRect& r, CompositeOperator op, WebBlendMode blendMode, bool useLowQualityScale) |
-{ |
- if (!image) |
- return; |
- drawImageBuffer(image, FloatRect(r), FloatRect(FloatPoint(), FloatSize(image->logicalSize())), op, blendMode, useLowQualityScale); |
-} |
- |
-void GraphicsContext::drawImageBuffer(ImageBuffer* image, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op, WebBlendMode blendMode) |
-{ |
- drawImageBuffer(image, FloatRect(IntRect(dest, srcRect.size())), FloatRect(srcRect), op, blendMode); |
-} |
- |
-void GraphicsContext::drawImageBuffer(ImageBuffer* image, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, WebBlendMode blendMode, bool useLowQualityScale) |
-{ |
- drawImageBuffer(image, FloatRect(dest), FloatRect(srcRect), op, blendMode, useLowQualityScale); |
-} |
- |
-void GraphicsContext::drawImageBuffer(ImageBuffer* image, const FloatRect& dest) |
-{ |
- if (!image) |
- return; |
- drawImageBuffer(image, dest, FloatRect(IntRect(IntPoint(), image->logicalSize()))); |
-} |
- |
-void GraphicsContext::drawImageBuffer(ImageBuffer* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op, WebBlendMode blendMode, bool useLowQualityScale) |
-{ |
- if (paintingDisabled() || !image) |
- return; |
- |
- if (useLowQualityScale) { |
- InterpolationQuality previousInterpolationQuality = imageInterpolationQuality(); |
- setImageInterpolationQuality(InterpolationLow); |
- image->draw(this, dest, src, op, blendMode, useLowQualityScale); |
- setImageInterpolationQuality(previousInterpolationQuality); |
- } else { |
- image->draw(this, dest, src, op, blendMode, useLowQualityScale); |
- } |
-} |
- |
-void GraphicsContext::writePixels(const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- m_canvas->writePixels(bitmap, x, y, config8888); |
- |
- if (m_trackOpaqueRegion) { |
- SkRect rect = SkRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()); |
- SkPaint paint; |
- |
- paint.setXfermodeMode(SkXfermode::kSrc_Mode); |
- m_opaqueRegion.didDrawRect(this, rect, paint, &bitmap); |
- } |
-} |
- |
-void GraphicsContext::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint* paint) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- m_canvas->drawBitmap(bitmap, left, top, paint); |
- |
- if (m_trackOpaqueRegion) { |
- SkRect rect = SkRect::MakeXYWH(left, top, bitmap.width(), bitmap.height()); |
- m_opaqueRegion.didDrawRect(this, rect, *paint, &bitmap); |
- } |
-} |
- |
-void GraphicsContext::drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, |
- const SkRect& dst, const SkPaint* paint) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- SkCanvas::DrawBitmapRectFlags flags = m_state->m_shouldClampToSourceRect ? SkCanvas::kNone_DrawBitmapRectFlag : SkCanvas::kBleed_DrawBitmapRectFlag; |
- |
- m_canvas->drawBitmapRectToRect(bitmap, src, dst, paint, flags); |
- |
- if (m_trackOpaqueRegion) |
- m_opaqueRegion.didDrawRect(this, dst, *paint, &bitmap); |
-} |
- |
-void GraphicsContext::drawOval(const SkRect& oval, const SkPaint& paint) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- m_canvas->drawOval(oval, paint); |
- |
- if (m_trackOpaqueRegion) |
- m_opaqueRegion.didDrawBounded(this, oval, paint); |
-} |
- |
-void GraphicsContext::drawPath(const SkPath& path, const SkPaint& paint) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- m_canvas->drawPath(path, paint); |
- |
- if (m_trackOpaqueRegion) |
- m_opaqueRegion.didDrawPath(this, path, paint); |
-} |
- |
-void GraphicsContext::drawRect(const SkRect& rect, const SkPaint& paint) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- m_canvas->drawRect(rect, paint); |
- |
- if (m_trackOpaqueRegion) |
- m_opaqueRegion.didDrawRect(this, rect, paint, 0); |
-} |
- |
-void GraphicsContext::didDrawRect(const SkRect& rect, const SkPaint& paint, const SkBitmap* bitmap) |
-{ |
- if (m_trackOpaqueRegion) |
- m_opaqueRegion.didDrawRect(this, rect, paint, bitmap); |
-} |
- |
-void GraphicsContext::drawPosText(const void* text, size_t byteLength, |
- const SkPoint pos[], const SkRect& textRect, const SkPaint& paint) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- m_canvas->drawPosText(text, byteLength, pos, paint); |
- didDrawTextInRect(textRect); |
- |
- // FIXME: compute bounds for positioned text. |
- if (m_trackOpaqueRegion) |
- m_opaqueRegion.didDrawUnbounded(this, paint, OpaqueRegionSkia::FillOrStroke); |
-} |
- |
-void GraphicsContext::drawPosTextH(const void* text, size_t byteLength, |
- const SkScalar xpos[], SkScalar constY, const SkRect& textRect, const SkPaint& paint) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- m_canvas->drawPosTextH(text, byteLength, xpos, constY, paint); |
- didDrawTextInRect(textRect); |
- |
- // FIXME: compute bounds for positioned text. |
- if (m_trackOpaqueRegion) |
- m_opaqueRegion.didDrawUnbounded(this, paint, OpaqueRegionSkia::FillOrStroke); |
-} |
- |
-void GraphicsContext::drawTextOnPath(const void* text, size_t byteLength, |
- const SkPath& path, const SkRect& textRect, const SkMatrix* matrix, const SkPaint& paint) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- m_canvas->drawTextOnPath(text, byteLength, path, matrix, paint); |
- didDrawTextInRect(textRect); |
- |
- // FIXME: compute bounds for positioned text. |
- if (m_trackOpaqueRegion) |
- m_opaqueRegion.didDrawUnbounded(this, paint, OpaqueRegionSkia::FillOrStroke); |
-} |
- |
-void GraphicsContext::fillPath(const Path& pathToFill) |
-{ |
- if (paintingDisabled() || pathToFill.isEmpty()) |
- return; |
- |
- // Use const_cast and temporarily modify the fill type instead of copying the path. |
- SkPath& path = const_cast<SkPath&>(pathToFill.skPath()); |
- SkPath::FillType previousFillType = path.getFillType(); |
- |
- SkPath::FillType temporaryFillType = m_state->m_fillRule == RULE_EVENODD ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType; |
- path.setFillType(temporaryFillType); |
- |
- SkPaint paint; |
- setupPaintForFilling(&paint); |
- drawPath(path, paint); |
- |
- path.setFillType(previousFillType); |
-} |
- |
-void GraphicsContext::fillRect(const FloatRect& rect) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- SkRect r = rect; |
- |
- SkPaint paint; |
- setupPaintForFilling(&paint); |
- drawRect(r, paint); |
-} |
- |
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- SkRect r = rect; |
- SkPaint paint; |
- setupPaintCommon(&paint); |
- paint.setColor(color.rgb()); |
- drawRect(r, paint); |
-} |
- |
-void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, |
- const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- if (topLeft.width() + topRight.width() > rect.width() |
- || bottomLeft.width() + bottomRight.width() > rect.width() |
- || topLeft.height() + bottomLeft.height() > rect.height() |
- || topRight.height() + bottomRight.height() > rect.height()) { |
- // Not all the radii fit, return a rect. This matches the behavior of |
- // Path::createRoundedRectangle. Without this we attempt to draw a round |
- // shadow for a square box. |
- fillRect(rect, color); |
- return; |
- } |
- |
- SkVector radii[4]; |
- setRadii(radii, topLeft, topRight, bottomRight, bottomLeft); |
- |
- SkRRect rr; |
- rr.setRectRadii(rect, radii); |
- |
- SkPaint paint; |
- setupPaintForFilling(&paint); |
- paint.setColor(color.rgb()); |
- |
- m_canvas->drawRRect(rr, paint); |
- |
- if (m_trackOpaqueRegion) |
- m_opaqueRegion.didDrawBounded(this, rr.getBounds(), paint); |
-} |
- |
-void GraphicsContext::fillEllipse(const FloatRect& ellipse) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- SkRect rect = ellipse; |
- SkPaint paint; |
- setupPaintForFilling(&paint); |
- drawOval(rect, paint); |
-} |
- |
-void GraphicsContext::strokePath(const Path& pathToStroke) |
-{ |
- if (paintingDisabled() || pathToStroke.isEmpty()) |
- return; |
- |
- const SkPath& path = pathToStroke.skPath(); |
- SkPaint paint; |
- setupPaintForStroking(&paint); |
- drawPath(path, paint); |
-} |
- |
-void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- SkPaint paint; |
- setupPaintForStroking(&paint); |
- paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth)); |
- // strokerect has special rules for CSS when the rect is degenerate: |
- // if width==0 && height==0, do nothing |
- // if width==0 || height==0, then just draw line for the other dimension |
- SkRect r(rect); |
- bool validW = r.width() > 0; |
- bool validH = r.height() > 0; |
- if (validW && validH) { |
- drawRect(r, paint); |
- } else if (validW || validH) { |
- // we are expected to respect the lineJoin, so we can't just call |
- // drawLine -- we have to create a path that doubles back on itself. |
- SkPath path; |
- path.moveTo(r.fLeft, r.fTop); |
- path.lineTo(r.fRight, r.fBottom); |
- path.close(); |
- drawPath(path, paint); |
- } |
-} |
- |
-void GraphicsContext::strokeEllipse(const FloatRect& ellipse) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- SkRect rect(ellipse); |
- SkPaint paint; |
- setupPaintForStroking(&paint); |
- drawOval(rect, paint); |
-} |
- |
-void GraphicsContext::clipRoundedRect(const RoundedRect& rect) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- SkVector radii[4]; |
- RoundedRect::Radii wkRadii = rect.radii(); |
- setRadii(radii, wkRadii.topLeft(), wkRadii.topRight(), wkRadii.bottomRight(), wkRadii.bottomLeft()); |
- |
- SkRRect r; |
- r.setRectRadii(rect.rect(), radii); |
- |
- clipRRect(r, AntiAliased); |
-} |
- |
-void GraphicsContext::clipOut(const Path& pathToClip) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- // Use const_cast and temporarily toggle the inverse fill type instead of copying the path. |
- SkPath& path = const_cast<SkPath&>(pathToClip.skPath()); |
- path.toggleInverseFillType(); |
- clipPath(path, AntiAliased); |
- path.toggleInverseFillType(); |
-} |
- |
-void GraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule) |
-{ |
- if (paintingDisabled() || pathToClip.isEmpty()) |
- return; |
- |
- // Use const_cast and temporarily modify the fill type instead of copying the path. |
- SkPath& path = const_cast<SkPath&>(pathToClip.skPath()); |
- SkPath::FillType previousFillType = path.getFillType(); |
- |
- SkPath::FillType temporaryFillType = clipRule == RULE_EVENODD ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType; |
- path.setFillType(temporaryFillType); |
- clipPath(path, AntiAliased); |
- |
- path.setFillType(previousFillType); |
-} |
- |
-void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialiased) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- if (numPoints <= 1) |
- return; |
- |
- SkPath path; |
- setPathFromConvexPoints(&path, numPoints, points); |
- clipPath(path, antialiased ? AntiAliased : NotAntiAliased); |
-} |
- |
-void GraphicsContext::clipOutRoundedRect(const RoundedRect& rect) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- if (!rect.isRounded()) { |
- clipOut(rect.rect()); |
- return; |
- } |
- |
- Path path; |
- path.addRoundedRect(rect); |
- clipOut(path); |
-} |
- |
-void GraphicsContext::canvasClip(const Path& pathToClip, WindRule clipRule) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- // Use const_cast and temporarily modify the fill type instead of copying the path. |
- SkPath& path = const_cast<SkPath&>(pathToClip.skPath()); |
- SkPath::FillType previousFillType = path.getFillType(); |
- |
- SkPath::FillType temporaryFillType = clipRule == RULE_EVENODD ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType; |
- path.setFillType(temporaryFillType); |
- clipPath(path); |
- |
- path.setFillType(previousFillType); |
-} |
- |
-bool GraphicsContext::clipRect(const SkRect& rect, AntiAliasingMode aa, SkRegion::Op op) |
-{ |
- if (paintingDisabled()) |
- return false; |
- |
- realizeSave(SkCanvas::kClip_SaveFlag); |
- |
- return m_canvas->clipRect(rect, op, aa == AntiAliased); |
-} |
- |
-bool GraphicsContext::clipPath(const SkPath& path, AntiAliasingMode aa, SkRegion::Op op) |
-{ |
- if (paintingDisabled()) |
- return false; |
- |
- realizeSave(SkCanvas::kClip_SaveFlag); |
- |
- return m_canvas->clipPath(path, op, aa == AntiAliased); |
-} |
- |
-bool GraphicsContext::clipRRect(const SkRRect& rect, AntiAliasingMode aa, SkRegion::Op op) |
-{ |
- if (paintingDisabled()) |
- return false; |
- |
- realizeSave(SkCanvas::kClip_SaveFlag); |
- |
- return m_canvas->clipRRect(rect, op, aa == AntiAliased); |
-} |
- |
-void GraphicsContext::rotate(float angleInRadians) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- realizeSave(SkCanvas::kMatrix_SaveFlag); |
- |
- m_canvas->rotate(WebCoreFloatToSkScalar(angleInRadians * (180.0f / 3.14159265f))); |
-} |
- |
-void GraphicsContext::translate(float w, float h) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- realizeSave(SkCanvas::kMatrix_SaveFlag); |
- |
- m_canvas->translate(WebCoreFloatToSkScalar(w), WebCoreFloatToSkScalar(h)); |
-} |
- |
-void GraphicsContext::scale(const FloatSize& size) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- realizeSave(SkCanvas::kMatrix_SaveFlag); |
- |
- m_canvas->scale(WebCoreFloatToSkScalar(size.width()), WebCoreFloatToSkScalar(size.height())); |
-} |
- |
-void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- SkAutoDataUnref url(SkData::NewWithCString(link.string().utf8().data())); |
- SkAnnotateRectWithURL(m_canvas, destRect, url.get()); |
-} |
- |
-void GraphicsContext::setURLFragmentForRect(const String& destName, const IntRect& rect) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- SkAutoDataUnref skDestName(SkData::NewWithCString(destName.utf8().data())); |
- SkAnnotateLinkToDestination(m_canvas, rect, skDestName.get()); |
-} |
- |
-void GraphicsContext::addURLTargetAtPoint(const String& name, const IntPoint& pos) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- SkAutoDataUnref nameData(SkData::NewWithCString(name.utf8().data())); |
- SkAnnotateNamedDestination(m_canvas, SkPoint::Make(pos.x(), pos.y()), nameData); |
-} |
- |
-AffineTransform GraphicsContext::getCTM(IncludeDeviceScale) const |
-{ |
- if (paintingDisabled()) |
- return AffineTransform(); |
- |
- SkMatrix m = getTotalMatrix(); |
- return AffineTransform(SkScalarToDouble(m.getScaleX()), |
- SkScalarToDouble(m.getSkewY()), |
- SkScalarToDouble(m.getSkewX()), |
- SkScalarToDouble(m.getScaleY()), |
- SkScalarToDouble(m.getTranslateX()), |
- SkScalarToDouble(m.getTranslateY())); |
-} |
- |
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, CompositeOperator op) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- CompositeOperator previousOperator = compositeOperation(); |
- setCompositeOperation(op); |
- fillRect(rect, color); |
- setCompositeOperation(previousOperator); |
-} |
- |
-void GraphicsContext::fillRoundedRect(const RoundedRect& rect, const Color& color) |
-{ |
- if (rect.isRounded()) |
- fillRoundedRect(rect.rect(), rect.radii().topLeft(), rect.radii().topRight(), rect.radii().bottomLeft(), rect.radii().bottomRight(), color); |
- else |
- fillRect(rect.rect(), color); |
-} |
- |
-void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const RoundedRect& roundedHoleRect, const Color& color) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- Path path; |
- path.addRect(rect); |
- |
- if (!roundedHoleRect.radii().isZero()) |
- path.addRoundedRect(roundedHoleRect); |
- else |
- path.addRect(roundedHoleRect.rect()); |
- |
- WindRule oldFillRule = fillRule(); |
- Color oldFillColor = fillColor(); |
- |
- setFillRule(RULE_EVENODD); |
- setFillColor(color); |
- |
- fillPath(path); |
- |
- setFillRule(oldFillRule); |
- setFillColor(oldFillColor); |
-} |
- |
-void GraphicsContext::clearRect(const FloatRect& rect) |
-{ |
- if (paintingDisabled()) |
- return; |
- |
- SkRect r = rect; |
- SkPaint paint; |
- setupPaintForFilling(&paint); |
- paint.setXfermodeMode(SkXfermode::kClear_Mode); |
- drawRect(r, paint); |
-} |
- |
-void GraphicsContext::adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, StrokeStyle penStyle) |
-{ |
- // For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic |
- // works out. For example, with a border width of 3, WebKit will pass us (y1+y2)/2, e.g., |
- // (50+53)/2 = 103/2 = 51 when we want 51.5. It is always true that an even width gave |
- // us a perfect position, but an odd width gave us a position that is off by exactly 0.5. |
- if (penStyle == DottedStroke || penStyle == DashedStroke) { |
- if (p1.x() == p2.x()) { |
- p1.setY(p1.y() + strokeWidth); |
- p2.setY(p2.y() - strokeWidth); |
- } else { |
- p1.setX(p1.x() + strokeWidth); |
- p2.setX(p2.x() - strokeWidth); |
- } |
- } |
- |
- if (static_cast<int>(strokeWidth) % 2) { //odd |
- if (p1.x() == p2.x()) { |
- // We're a vertical line. Adjust our x. |
- p1.setX(p1.x() + 0.5f); |
- p2.setX(p2.x() + 0.5f); |
- } else { |
- // We're a horizontal line. Adjust our y. |
- p1.setY(p1.y() + 0.5f); |
- p2.setY(p2.y() + 0.5f); |
- } |
- } |
-} |
- |
-PassOwnPtr<ImageBuffer> GraphicsContext::createCompatibleBuffer(const IntSize& size, bool hasAlpha) const |
-{ |
- // Make the buffer larger if the context's transform is scaling it so we need a higher |
- // resolution than one pixel per unit. Also set up a corresponding scale factor on the |
- // graphics context. |
- |
- AffineTransform transform = getCTM(DefinitelyIncludeDeviceScale); |
- IntSize scaledSize(static_cast<int>(ceil(size.width() * transform.xScale())), static_cast<int>(ceil(size.height() * transform.yScale()))); |
- |
- OwnPtr<ImageBuffer> buffer = ImageBuffer::createCompatibleBuffer(scaledSize, 1, this, hasAlpha); |
- if (!buffer) |
- return nullptr; |
- |
- buffer->context()->scale(FloatSize(static_cast<float>(scaledSize.width()) / size.width(), |
- static_cast<float>(scaledSize.height()) / size.height())); |
- |
- return buffer.release(); |
-} |
- |
-void GraphicsContext::addCornerArc(SkPath* path, const SkRect& rect, const IntSize& size, int startAngle) |
-{ |
- SkIRect ir; |
- int rx = SkMin32(SkScalarRound(rect.width()), size.width()); |
- int ry = SkMin32(SkScalarRound(rect.height()), size.height()); |
- |
- ir.set(-rx, -ry, rx, ry); |
- switch (startAngle) { |
- case 0: |
- ir.offset(rect.fRight - ir.fRight, rect.fBottom - ir.fBottom); |
- break; |
- case 90: |
- ir.offset(rect.fLeft - ir.fLeft, rect.fBottom - ir.fBottom); |
- break; |
- case 180: |
- ir.offset(rect.fLeft - ir.fLeft, rect.fTop - ir.fTop); |
- break; |
- case 270: |
- ir.offset(rect.fRight - ir.fRight, rect.fTop - ir.fTop); |
- break; |
- default: |
- ASSERT(0); |
- } |
- |
- SkRect r; |
- r.set(ir); |
- path->arcTo(r, SkIntToScalar(startAngle), SkIntToScalar(90), false); |
-} |
- |
-void GraphicsContext::setPathFromConvexPoints(SkPath* path, size_t numPoints, const FloatPoint* points) |
-{ |
- path->incReserve(numPoints); |
- path->moveTo(WebCoreFloatToSkScalar(points[0].x()), |
- WebCoreFloatToSkScalar(points[0].y())); |
- for (size_t i = 1; i < numPoints; ++i) { |
- path->lineTo(WebCoreFloatToSkScalar(points[i].x()), |
- WebCoreFloatToSkScalar(points[i].y())); |
- } |
- |
- /* The code used to just blindly call this |
- path->setIsConvex(true); |
- But webkit can sometimes send us non-convex 4-point values, so we mark the path's |
- convexity as unknown, so it will get computed by skia at draw time. |
- See crbug.com 108605 |
- */ |
- SkPath::Convexity convexity = SkPath::kConvex_Convexity; |
- if (numPoints == 4) |
- convexity = SkPath::kUnknown_Convexity; |
- path->setConvexity(convexity); |
-} |
- |
-void GraphicsContext::setupPaintCommon(SkPaint* paint) const |
-{ |
-#if defined(SK_DEBUG) |
- { |
- SkPaint defaultPaint; |
- SkASSERT(*paint == defaultPaint); |
- } |
-#endif |
- |
- paint->setAntiAlias(m_state->m_shouldAntialias); |
- |
- if (!SkXfermode::IsMode(m_state->m_xferMode.get(), SkXfermode::kSrcOver_Mode)) |
- paint->setXfermode(m_state->m_xferMode.get()); |
- |
- if (m_state->m_looper) |
- paint->setLooper(m_state->m_looper.get()); |
- |
- paint->setColorFilter(m_state->m_colorFilter.get()); |
-} |
- |
-void GraphicsContext::drawOuterPath(const SkPath& path, SkPaint& paint, int width) |
-{ |
-#if OS(MACOSX) |
- paint.setAlpha(64); |
- paint.setStrokeWidth(width); |
- paint.setPathEffect(new SkCornerPathEffect((width - 1) * 0.5f))->unref(); |
-#else |
- paint.setStrokeWidth(1); |
- paint.setPathEffect(new SkCornerPathEffect(1))->unref(); |
-#endif |
- drawPath(path, paint); |
-} |
- |
-void GraphicsContext::drawInnerPath(const SkPath& path, SkPaint& paint, int width) |
-{ |
-#if OS(MACOSX) |
- paint.setAlpha(128); |
- paint.setStrokeWidth(width * 0.5f); |
- drawPath(path, paint); |
-#endif |
-} |
- |
-void GraphicsContext::setRadii(SkVector* radii, IntSize topLeft, IntSize topRight, IntSize bottomRight, IntSize bottomLeft) |
-{ |
- radii[SkRRect::kUpperLeft_Corner].set(SkIntToScalar(topLeft.width()), |
- SkIntToScalar(topLeft.height())); |
- radii[SkRRect::kUpperRight_Corner].set(SkIntToScalar(topRight.width()), |
- SkIntToScalar(topRight.height())); |
- radii[SkRRect::kLowerRight_Corner].set(SkIntToScalar(bottomRight.width()), |
- SkIntToScalar(bottomRight.height())); |
- radii[SkRRect::kLowerLeft_Corner].set(SkIntToScalar(bottomLeft.width()), |
- SkIntToScalar(bottomLeft.height())); |
-} |
- |
-PassRefPtr<SkColorFilter> GraphicsContext::WebCoreColorFilterToSkiaColorFilter(ColorFilter colorFilter) |
-{ |
- switch (colorFilter) { |
- case ColorFilterLuminanceToAlpha: |
- return adoptRef(SkLumaColorFilter::Create()); |
- case ColorFilterLinearRGBToSRGB: |
- return ImageBuffer::createColorSpaceFilter(ColorSpaceLinearRGB, ColorSpaceDeviceRGB); |
- case ColorFilterSRGBToLinearRGB: |
- return ImageBuffer::createColorSpaceFilter(ColorSpaceDeviceRGB, ColorSpaceLinearRGB); |
- case ColorFilterNone: |
- break; |
- default: |
- ASSERT_NOT_REACHED(); |
- break; |
- } |
- |
- return 0; |
-} |
- |
- |
-#if OS(MACOSX) |
-CGColorSpaceRef deviceRGBColorSpaceRef() |
-{ |
- static CGColorSpaceRef deviceSpace = CGColorSpaceCreateDeviceRGB(); |
- return deviceSpace; |
-} |
-#else |
-void GraphicsContext::draw2xMarker(SkBitmap* bitmap, int index) |
-{ |
- const SkPMColor lineColor = lineColors(index); |
- const SkPMColor antiColor1 = antiColors1(index); |
- const SkPMColor antiColor2 = antiColors2(index); |
- |
- uint32_t* row1 = bitmap->getAddr32(0, 0); |
- uint32_t* row2 = bitmap->getAddr32(0, 1); |
- uint32_t* row3 = bitmap->getAddr32(0, 2); |
- uint32_t* row4 = bitmap->getAddr32(0, 3); |
- |
- // Pattern: X0o o0X0o o0 |
- // XX0o o0XXX0o o0X |
- // o0XXX0o o0XXX0o |
- // o0X0o o0X0o |
- const SkPMColor row1Color[] = { lineColor, antiColor1, antiColor2, 0, 0, 0, antiColor2, antiColor1 }; |
- const SkPMColor row2Color[] = { lineColor, lineColor, antiColor1, antiColor2, 0, antiColor2, antiColor1, lineColor }; |
- const SkPMColor row3Color[] = { 0, antiColor2, antiColor1, lineColor, lineColor, lineColor, antiColor1, antiColor2 }; |
- const SkPMColor row4Color[] = { 0, 0, antiColor2, antiColor1, lineColor, antiColor1, antiColor2, 0 }; |
- |
- for (int x = 0; x < bitmap->width() + 8; x += 8) { |
- int count = std::min(bitmap->width() - x, 8); |
- if (count > 0) { |
- memcpy(row1 + x, row1Color, count * sizeof(SkPMColor)); |
- memcpy(row2 + x, row2Color, count * sizeof(SkPMColor)); |
- memcpy(row3 + x, row3Color, count * sizeof(SkPMColor)); |
- memcpy(row4 + x, row4Color, count * sizeof(SkPMColor)); |
- } |
- } |
-} |
- |
-void GraphicsContext::draw1xMarker(SkBitmap* bitmap, int index) |
-{ |
- const uint32_t lineColor = lineColors(index); |
- const uint32_t antiColor = antiColors2(index); |
- |
- // Pattern: X o o X o o X |
- // o X o o X o |
- uint32_t* row1 = bitmap->getAddr32(0, 0); |
- uint32_t* row2 = bitmap->getAddr32(0, 1); |
- for (int x = 0; x < bitmap->width(); x++) { |
- switch (x % 4) { |
- case 0: |
- row1[x] = lineColor; |
- break; |
- case 1: |
- row1[x] = antiColor; |
- row2[x] = antiColor; |
- break; |
- case 2: |
- row2[x] = lineColor; |
- break; |
- case 3: |
- row1[x] = antiColor; |
- row2[x] = antiColor; |
- break; |
- } |
- } |
-} |
- |
-const SkPMColor GraphicsContext::lineColors(int index) |
-{ |
- static const SkPMColor colors[] = { |
- SkPreMultiplyARGB(0xFF, 0xFF, 0x00, 0x00), // Opaque red. |
- SkPreMultiplyARGB(0xFF, 0xC0, 0xC0, 0xC0) // Opaque gray. |
- }; |
- |
- return colors[index]; |
-} |
- |
-const SkPMColor GraphicsContext::antiColors1(int index) |
-{ |
- static const SkPMColor colors[] = { |
- SkPreMultiplyARGB(0xB0, 0xFF, 0x00, 0x00), // Semitransparent red. |
- SkPreMultiplyARGB(0xB0, 0xC0, 0xC0, 0xC0) // Semitransparent gray. |
- }; |
- |
- return colors[index]; |
-} |
- |
-const SkPMColor GraphicsContext::antiColors2(int index) |
-{ |
- static const SkPMColor colors[] = { |
- SkPreMultiplyARGB(0x60, 0xFF, 0x00, 0x00), // More transparent red |
- SkPreMultiplyARGB(0x60, 0xC0, 0xC0, 0xC0) // More transparent gray |
- }; |
- |
- return colors[index]; |
-} |
-#endif |
- |
-void GraphicsContext::setupShader(SkPaint* paint, Gradient* grad, Pattern* pat, SkColor color) const |
-{ |
- RefPtr<SkShader> shader; |
- |
- if (grad) { |
- shader = grad->shader(); |
- color = SK_ColorBLACK; |
- } else if (pat) { |
- shader = pat->shader(); |
- color = SK_ColorBLACK; |
- paint->setFilterBitmap(imageInterpolationQuality() != InterpolationNone); |
- } |
- |
- paint->setColor(m_state->applyAlpha(color)); |
- |
- if (!shader) |
- return; |
- |
- paint->setShader(shader.get()); |
-} |
- |
-void GraphicsContext::didDrawTextInRect(const SkRect& textRect) |
-{ |
- if (m_trackTextRegion) { |
- TRACE_EVENT0("skia", "PlatformContextSkia::trackTextRegion"); |
- m_textRegion.join(textRect); |
- } |
-} |
- |
-} |