Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / graphics / GraphicsContext.cpp
index 0856f57..f43c59c 100644 (file)
@@ -91,8 +91,8 @@ private:
 
 } // unnamed namespace
 
-struct GraphicsContext::DeferredSaveState {
-    DeferredSaveState(unsigned mask, int count) : m_flags(mask), m_restoreCount(count) { }
+struct GraphicsContext::CanvasSaveState {
+    CanvasSaveState(unsigned mask, int count) : m_flags(mask), m_restoreCount(count) { }
 
     unsigned m_flags;
     int m_restoreCount;
@@ -113,7 +113,9 @@ struct GraphicsContext::RecordingState {
 
 GraphicsContext::GraphicsContext(SkCanvas* canvas)
     : m_canvas(canvas)
-    , m_deferredSaveFlags(0)
+    , m_paintStateStack()
+    , m_paintStateIndex(0)
+    , m_canvasSaveFlags(0)
     , m_annotationMode(0)
 #if !ASSERT_DISABLED
     , m_annotationCount(0)
@@ -127,13 +129,16 @@ GraphicsContext::GraphicsContext(SkCanvas* canvas)
     , m_isCertainlyOpaque(true)
     , m_printing(false)
 {
-    m_stateStack.append(adoptPtr(new GraphicsContextState()));
-    m_state = m_stateStack.last().get();
+    // FIXME: Do some tests to determine how many states are typically used, and allocate
+    // several here.
+    m_paintStateStack.append(GraphicsContextState::create());
+    m_paintState = m_paintStateStack.last().get();
 }
 
 GraphicsContext::~GraphicsContext()
 {
-    ASSERT(m_stateStack.size() == 1);
+    ASSERT(!m_paintStateIndex);
+    ASSERT(!m_paintState->m_saveCount);
     ASSERT(!m_annotationCount);
     ASSERT(!m_layerCount);
     ASSERT(m_recordingStateStack.isEmpty());
@@ -155,11 +160,10 @@ void GraphicsContext::save()
     if (paintingDisabled())
         return;
 
-    m_stateStack.append(m_state->clone());
-    m_state = m_stateStack.last().get();
+    m_paintState->m_saveCount++;
 
-    m_saveStateStack.append(DeferredSaveState(m_deferredSaveFlags, m_canvas->getSaveCount()));
-    m_deferredSaveFlags |= SkCanvas::kMatrixClip_SaveFlag;
+    m_canvasStateStack.append(CanvasSaveState(m_canvasSaveFlags, m_canvas->getSaveCount()));
+    m_canvasSaveFlags |= SkCanvas::kMatrixClip_SaveFlag;
 }
 
 void GraphicsContext::restore()
@@ -167,17 +171,21 @@ void GraphicsContext::restore()
     if (paintingDisabled())
         return;
 
-    if (m_stateStack.size() == 1) {
+    if (!m_paintStateIndex && !m_paintState->m_saveCount) {
         WTF_LOG_ERROR("ERROR void GraphicsContext::restore() stack is empty");
         return;
     }
 
-    m_stateStack.removeLast();
-    m_state = m_stateStack.last().get();
+    if (m_paintState->m_saveCount) {
+        m_paintState->m_saveCount--;
+    } else {
+        m_paintStateIndex--;
+        m_paintState = m_paintStateStack[m_paintStateIndex].get();
+    }
 
-    DeferredSaveState savedState = m_saveStateStack.last();
-    m_saveStateStack.removeLast();
-    m_deferredSaveFlags = savedState.m_flags;
+    CanvasSaveState savedState = m_canvasStateStack.last();
+    m_canvasStateStack.removeLast();
+    m_canvasSaveFlags = savedState.m_flags;
     m_canvas->restoreToCount(savedState.m_restoreCount);
 }
 
@@ -186,7 +194,7 @@ void GraphicsContext::saveLayer(const SkRect* bounds, const SkPaint* paint, SkCa
     if (paintingDisabled())
         return;
 
-    realizeSave(SkCanvas::kMatrixClip_SaveFlag);
+    realizeCanvasSave(SkCanvas::kMatrixClip_SaveFlag);
 
     m_canvas->saveLayer(bounds, paint, saveFlags);
     if (bounds)
@@ -241,9 +249,10 @@ void GraphicsContext::endAnnotation()
 
 void GraphicsContext::setStrokeColor(const Color& color)
 {
-    m_state->m_strokeData.setColor(color);
-    m_state->m_strokeData.clearGradient();
-    m_state->m_strokeData.clearPattern();
+    GraphicsContextState* stateToSet = mutableState();
+    stateToSet->m_strokeData.setColor(color);
+    stateToSet->m_strokeData.clearGradient();
+    stateToSet->m_strokeData.clearPattern();
 }
 
 void GraphicsContext::setStrokePattern(PassRefPtr<Pattern> pattern)
@@ -256,8 +265,9 @@ void GraphicsContext::setStrokePattern(PassRefPtr<Pattern> pattern)
         setStrokeColor(Color::black);
         return;
     }
-    m_state->m_strokeData.clearGradient();
-    m_state->m_strokeData.setPattern(pattern);
+    GraphicsContextState* stateToSet = mutableState();
+    stateToSet->m_strokeData.clearGradient();
+    stateToSet->m_strokeData.setPattern(pattern);
 }
 
 void GraphicsContext::setStrokeGradient(PassRefPtr<Gradient> gradient)
@@ -270,15 +280,17 @@ void GraphicsContext::setStrokeGradient(PassRefPtr<Gradient> gradient)
         setStrokeColor(Color::black);
         return;
     }
-    m_state->m_strokeData.setGradient(gradient);
-    m_state->m_strokeData.clearPattern();
+    GraphicsContextState* stateToSet = mutableState();
+    stateToSet->m_strokeData.setGradient(gradient);
+    stateToSet->m_strokeData.clearPattern();
 }
 
 void GraphicsContext::setFillColor(const Color& color)
 {
-    m_state->m_fillColor = color;
-    m_state->m_fillGradient.clear();
-    m_state->m_fillPattern.clear();
+    GraphicsContextState* stateToSet = mutableState();
+    stateToSet->m_fillColor = color;
+    stateToSet->m_fillGradient.clear();
+    stateToSet->m_fillPattern.clear();
 }
 
 void GraphicsContext::setFillPattern(PassRefPtr<Pattern> pattern)
@@ -291,8 +303,10 @@ void GraphicsContext::setFillPattern(PassRefPtr<Pattern> pattern)
         setFillColor(Color::black);
         return;
     }
-    m_state->m_fillGradient.clear();
-    m_state->m_fillPattern = pattern;
+
+    GraphicsContextState* stateToSet = mutableState();
+    stateToSet->m_fillGradient.clear();
+    stateToSet->m_fillPattern = pattern;
 }
 
 void GraphicsContext::setFillGradient(PassRefPtr<Gradient> gradient)
@@ -305,8 +319,10 @@ void GraphicsContext::setFillGradient(PassRefPtr<Gradient> gradient)
         setFillColor(Color::black);
         return;
     }
-    m_state->m_fillGradient = gradient;
-    m_state->m_fillPattern.clear();
+
+    GraphicsContextState* stateToSet = mutableState();
+    stateToSet->m_fillGradient = gradient;
+    stateToSet->m_fillPattern.clear();
 }
 
 void GraphicsContext::setShadow(const FloatSize& offset, float blur, const Color& color,
@@ -332,7 +348,7 @@ void GraphicsContext::setDrawLooper(const DrawLooper& drawLooper)
     if (paintingDisabled())
         return;
 
-    m_state->m_looper = drawLooper.skDrawLooper();
+    mutableState()->m_looper = drawLooper.skDrawLooper();
 }
 
 void GraphicsContext::clearDrawLooper()
@@ -340,17 +356,17 @@ void GraphicsContext::clearDrawLooper()
     if (paintingDisabled())
         return;
 
-    m_state->m_looper.clear();
+    mutableState()->m_looper.clear();
 }
 
 bool GraphicsContext::hasShadow() const
 {
-    return !!m_state->m_looper;
+    return !!immutableState()->m_looper;
 }
 
 int GraphicsContext::getNormalizedAlpha() const
 {
-    int alpha = roundf(m_state->m_alpha * 256);
+    int alpha = roundf(immutableState()->m_alpha * 256);
     if (alpha > 255)
         alpha = 255;
     else if (alpha < 0)
@@ -427,22 +443,25 @@ bool GraphicsContext::couldUseLCDRenderedText()
 
 void GraphicsContext::setCompositeOperation(CompositeOperator compositeOperation, WebBlendMode blendMode)
 {
-    m_state->m_compositeOperator = compositeOperation;
-    m_state->m_blendMode = blendMode;
-    m_state->m_xferMode = WebCoreCompositeToSkiaComposite(compositeOperation, blendMode);
+    GraphicsContextState* stateToSet = mutableState();
+    stateToSet->m_compositeOperator = compositeOperation;
+    stateToSet->m_blendMode = blendMode;
+    stateToSet->m_xferMode = WebCoreCompositeToSkiaComposite(compositeOperation, blendMode);
 }
 
 SkColorFilter* GraphicsContext::colorFilter()
 {
-    return m_state->m_colorFilter.get();
+    return immutableState()->m_colorFilter.get();
 }
 
 void GraphicsContext::setColorFilter(ColorFilter colorFilter)
 {
+    GraphicsContextState* stateToSet = mutableState();
+
     // 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);
+    ASSERT(!stateToSet->m_colorFilter);
+    stateToSet->m_colorFilter = WebCoreColorFilterToSkiaColorFilter(colorFilter);
 }
 
 bool GraphicsContext::readPixels(SkBitmap* bitmap, int x, int y, SkCanvas::Config8888 config8888)
@@ -458,7 +477,7 @@ void GraphicsContext::setMatrix(const SkMatrix& matrix)
     if (paintingDisabled())
         return;
 
-    realizeSave(SkCanvas::kMatrix_SaveFlag);
+    realizeCanvasSave(SkCanvas::kMatrix_SaveFlag);
 
     m_canvas->setMatrix(matrix);
 }
@@ -468,17 +487,18 @@ bool GraphicsContext::concat(const SkMatrix& matrix)
     if (paintingDisabled())
         return false;
 
+
     if (matrix.isIdentity())
         return true;
 
-    realizeSave(SkCanvas::kMatrix_SaveFlag);
+    realizeCanvasSave(SkCanvas::kMatrix_SaveFlag);
 
     return m_canvas->concat(matrix);
 }
 
 void GraphicsContext::beginTransparencyLayer(float opacity, const FloatRect* bounds)
 {
-    beginLayer(opacity, m_state->m_compositeOperator, bounds);
+    beginLayer(opacity, immutableState()->m_compositeOperator, bounds);
 }
 
 void GraphicsContext::beginLayer(float opacity, CompositeOperator op, const FloatRect* bounds, ColorFilter colorFilter, ImageFilter* imageFilter)
@@ -494,7 +514,7 @@ void GraphicsContext::beginLayer(float opacity, CompositeOperator op, const Floa
 
     SkPaint layerPaint;
     layerPaint.setAlpha(static_cast<unsigned char>(opacity * 255));
-    layerPaint.setXfermode(WebCoreCompositeToSkiaComposite(op, m_state->m_blendMode).get());
+    layerPaint.setXfermode(WebCoreCompositeToSkiaComposite(op, m_paintState->m_blendMode).get());
     layerPaint.setColorFilter(WebCoreColorFilterToSkiaColorFilter(colorFilter).get());
     layerPaint.setImageFilter(imageFilter);
 
@@ -572,7 +592,7 @@ void GraphicsContext::drawDisplayList(DisplayList* displayList)
     if (paintingDisabled() || displayList->bounds().isEmpty())
         return;
 
-    realizeSave(SkCanvas::kMatrixClip_SaveFlag);
+    realizeCanvasSave(SkCanvas::kMatrixClip_SaveFlag);
 
     const FloatRect& bounds = displayList->bounds();
     if (bounds.x() || bounds.y())
@@ -591,7 +611,7 @@ void GraphicsContext::setupPaintForFilling(SkPaint* paint) const
 
     setupPaintCommon(paint);
 
-    setupShader(paint, m_state->m_fillGradient.get(), m_state->m_fillPattern.get(), m_state->m_fillColor.rgb());
+    setupShader(paint, immutableState()->m_fillGradient.get(), immutableState()->m_fillPattern.get(), immutableState()->m_fillColor.rgb());
 }
 
 float GraphicsContext::setupPaintForStroking(SkPaint* paint, int length) const
@@ -601,10 +621,10 @@ float GraphicsContext::setupPaintForStroking(SkPaint* paint, int length) const
 
     setupPaintCommon(paint);
 
-    setupShader(paint, m_state->m_strokeData.gradient(), m_state->m_strokeData.pattern(),
-        m_state->m_strokeData.color().rgb());
+    setupShader(paint, immutableState()->m_strokeData.gradient(), immutableState()->m_strokeData.pattern(),
+        immutableState()->m_strokeData.color().rgb());
 
-    return m_state->m_strokeData.setupPaint(paint, length);
+    return immutableState()->m_strokeData.setupPaint(paint, length);
 }
 
 void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias)
@@ -983,13 +1003,13 @@ void GraphicsContext::drawRect(const IntRect& rect)
 
     SkRect skRect = rect;
     SkPaint paint;
-    int fillcolorNotTransparent = m_state->m_fillColor.rgb() & 0xFF000000;
+    int fillcolorNotTransparent = m_paintState->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)) {
+    if (m_paintState->m_strokeData.style() != NoStroke && (m_paintState->m_strokeData.color().rgb() & 0xFF000000)) {
         // We do a fill of four rects to simulate the stroke of a border.
         paint.reset();
         setupPaintForFilling(&paint);
@@ -1237,7 +1257,7 @@ void GraphicsContext::drawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
     if (paintingDisabled())
         return;
 
-    SkCanvas::DrawBitmapRectFlags flags = m_state->m_shouldClampToSourceRect ? SkCanvas::kNone_DrawBitmapRectFlag : SkCanvas::kBleed_DrawBitmapRectFlag;
+    SkCanvas::DrawBitmapRectFlags flags = m_paintState->m_shouldClampToSourceRect ? SkCanvas::kNone_DrawBitmapRectFlag : SkCanvas::kBleed_DrawBitmapRectFlag;
 
     m_canvas->drawBitmapRectToRect(bitmap, src, dst, paint, flags);
 
@@ -1335,7 +1355,7 @@ void GraphicsContext::fillPath(const Path& pathToFill)
     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;
+    SkPath::FillType temporaryFillType = m_paintState->m_fillRule == RULE_EVENODD ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType;
     path.setFillType(temporaryFillType);
 
     SkPaint paint;
@@ -1554,7 +1574,7 @@ bool GraphicsContext::clipRect(const SkRect& rect, AntiAliasingMode aa, SkRegion
     if (paintingDisabled())
         return false;
 
-    realizeSave(SkCanvas::kClip_SaveFlag);
+    realizeCanvasSave(SkCanvas::kClip_SaveFlag);
 
     return m_canvas->clipRect(rect, op, aa == AntiAliased);
 }
@@ -1564,7 +1584,7 @@ bool GraphicsContext::clipPath(const SkPath& path, AntiAliasingMode aa, SkRegion
     if (paintingDisabled())
         return false;
 
-    realizeSave(SkCanvas::kClip_SaveFlag);
+    realizeCanvasSave(SkCanvas::kClip_SaveFlag);
 
     return m_canvas->clipPath(path, op, aa == AntiAliased);
 }
@@ -1574,7 +1594,7 @@ bool GraphicsContext::clipRRect(const SkRRect& rect, AntiAliasingMode aa, SkRegi
     if (paintingDisabled())
         return false;
 
-    realizeSave(SkCanvas::kClip_SaveFlag);
+    realizeCanvasSave(SkCanvas::kClip_SaveFlag);
 
     return m_canvas->clipRRect(rect, op, aa == AntiAliased);
 }
@@ -1584,7 +1604,7 @@ void GraphicsContext::rotate(float angleInRadians)
     if (paintingDisabled())
         return;
 
-    realizeSave(SkCanvas::kMatrix_SaveFlag);
+    realizeCanvasSave(SkCanvas::kMatrix_SaveFlag);
 
     m_canvas->rotate(WebCoreFloatToSkScalar(angleInRadians * (180.0f / 3.14159265f)));
 }
@@ -1597,7 +1617,7 @@ void GraphicsContext::translate(float w, float h)
     if (!w && !h)
         return;
 
-    realizeSave(SkCanvas::kMatrix_SaveFlag);
+    realizeCanvasSave(SkCanvas::kMatrix_SaveFlag);
 
     m_canvas->translate(WebCoreFloatToSkScalar(w), WebCoreFloatToSkScalar(h));
 }
@@ -1610,7 +1630,7 @@ void GraphicsContext::scale(const FloatSize& size)
     if (size.width() == 1.0f && size.height() == 1.0f)
         return;
 
-    realizeSave(SkCanvas::kMatrix_SaveFlag);
+    realizeCanvasSave(SkCanvas::kMatrix_SaveFlag);
 
     m_canvas->scale(WebCoreFloatToSkScalar(size.width()), WebCoreFloatToSkScalar(size.height()));
 }
@@ -1823,15 +1843,15 @@ void GraphicsContext::setupPaintCommon(SkPaint* paint) const
     }
 #endif
 
-    paint->setAntiAlias(m_state->m_shouldAntialias);
+    paint->setAntiAlias(m_paintState->m_shouldAntialias);
 
-    if (!SkXfermode::IsMode(m_state->m_xferMode.get(), SkXfermode::kSrcOver_Mode))
-        paint->setXfermode(m_state->m_xferMode.get());
+    if (!SkXfermode::IsMode(m_paintState->m_xferMode.get(), SkXfermode::kSrcOver_Mode))
+        paint->setXfermode(m_paintState->m_xferMode.get());
 
-    if (m_state->m_looper)
-        paint->setLooper(m_state->m_looper.get());
+    if (m_paintState->m_looper)
+        paint->setLooper(m_paintState->m_looper.get());
 
-    paint->setColorFilter(m_state->m_colorFilter.get());
+    paint->setColorFilter(m_paintState->m_colorFilter.get());
 }
 
 void GraphicsContext::drawOuterPath(const SkPath& path, SkPaint& paint, int width)
@@ -1998,7 +2018,7 @@ void GraphicsContext::setupShader(SkPaint* paint, Gradient* grad, Pattern* pat,
         paint->setFilterBitmap(imageInterpolationQuality() != InterpolationNone);
     }
 
-    paint->setColor(m_state->applyAlpha(color));
+    paint->setColor(m_paintState->applyAlpha(color));
 
     if (!shader)
         return;