diff options
author | John Reck <jreck@google.com> | 2012-07-12 19:45:44 -0700 |
---|---|---|
committer | John Reck <jreck@google.com> | 2012-07-13 11:17:44 -0700 |
commit | 8ad43ea5cc2ec08eaf11619f6c543e14bb5e1506 (patch) | |
tree | 434696d55472a0c2d91d3da7b1211a105278defb /Source/WebCore/platform/graphics/android/context | |
parent | 51d890c9af6c8f35ddcdf8176b4598d4744a67af (diff) | |
download | external_webkit-8ad43ea5cc2ec08eaf11619f6c543e14bb5e1506.zip external_webkit-8ad43ea5cc2ec08eaf11619f6c543e14bb5e1506.tar.gz external_webkit-8ad43ea5cc2ec08eaf11619f6c543e14bb5e1506.tar.bz2 |
Handle Matrixes
Make sure to take into account the current matrix to calculate the right
global bounds
Tag operations with the matrix that affected their drawing
Change-Id: Iadda9f3849dc3df1507e63423ff8d3ad0f37d74e
Diffstat (limited to 'Source/WebCore/platform/graphics/android/context')
3 files changed, 86 insertions, 14 deletions
diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h index 3f39b38..9ecf5c5 100644 --- a/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h +++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h @@ -102,9 +102,14 @@ public: Operation() : m_state(0) + , m_matrix(0) {} + // This m_state is applied by ourselves PlatformGraphicsContext::State* m_state; + // This m_matrix is applied by Recording::draw + SkMatrix* m_matrix; + bool apply(PlatformGraphicsContext* context) { if (m_state) context->setRawState(m_state); diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp index e6ae9be..ed7e864 100644 --- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp @@ -63,6 +63,7 @@ public: ~RecordingImpl() { clearTree(); clearStates(); + clearMatrixes(); } PlatformGraphicsContext::State* getState(PlatformGraphicsContext::State* inState) { @@ -75,6 +76,11 @@ public: return state; } + SkMatrix* cloneMatrix(const SkMatrix& matrix) { + m_matrixes.append(new SkMatrix(matrix)); + return m_matrixes.last(); + } + RecordingTree m_tree; int m_nodeCount; @@ -96,8 +102,15 @@ private: m_states.clear(); } + void clearMatrixes() { + for (size_t i = 0; i < m_matrixes.size(); i++) + delete m_matrixes[i]; + m_matrixes.clear(); + } + // TODO: Use a global pool? StateHashSet m_states; + Vector<SkMatrix*> m_matrixes; }; Recording::~Recording() @@ -132,14 +145,32 @@ void Recording::draw(SkCanvas* canvas) float searchMax[] = {clip.fRight, clip.fBottom}; m_recording->m_tree.Search(searchMin, searchMax, GatherSearchResults, &nodes); size_t count = nodes.size(); - ALOGV("Drawing %d nodes out of %d", count, m_recording->m_nodeCount); + ALOGV("Drawing %d nodes out of %d (state storage=%d)", count, + m_recording->m_nodeCount, sizeof(PlatformGraphicsContext::State) * m_recording->m_states.size()); if (count) { nonCopyingSort(nodes.begin(), nodes.end(), CompareRecordingDataOrder); PlatformGraphicsContextSkia context(canvas); - for (size_t i = 0; i < count; i++) - nodes[i]->m_operation->apply(&context); + SkMatrix* matrix = 0; + int saveCount = 0; + for (size_t i = 0; i < count; i++) { + GraphicsOperation::Operation* op = nodes[i]->m_operation; + SkMatrix* opMatrix = op->m_matrix; + if (opMatrix != matrix) { + matrix = opMatrix; + if (saveCount) { + canvas->restoreToCount(saveCount); + saveCount = 0; + } + if (!matrix->isIdentity()) { + saveCount = canvas->save(SkCanvas::kMatrix_SaveFlag); + canvas->concat(*matrix); + } + } + op->apply(&context); + } + if (saveCount) + canvas->restoreToCount(saveCount); } - ALOGV("Using %dkb for state storage", (sizeof(PlatformGraphicsContext::State) * m_recording->m_states.size()) / 1024); } void Recording::setRecording(RecordingImpl* impl) @@ -158,9 +189,12 @@ void Recording::setRecording(RecordingImpl* impl) PlatformGraphicsContextRecording::PlatformGraphicsContextRecording(Recording* recording) : PlatformGraphicsContext() , mPicture(0) + , mCurrentMatrix(&mRootMatrix) , mRecording(recording) , mOperationState(0) + , mOperationMatrix(0) { + mRootMatrix.setIdentity(); if (mRecording) mRecording->setRecording(new RecordingImpl()); } @@ -206,6 +240,8 @@ void PlatformGraphicsContextRecording::save() { PlatformGraphicsContext::save(); mRecordingStateStack.append(new GraphicsOperation::Save()); + mCurrentMatrix = &(mRecordingStateStack.last().mMatrix); + mCurrentMatrix->setIdentity(); } void PlatformGraphicsContextRecording::restore() @@ -217,6 +253,10 @@ void PlatformGraphicsContextRecording::restore() appendDrawingOperation(state.mSaveOperation, state.mBounds); else delete state.mSaveOperation; + if (mRecordingStateStack.size()) + mCurrentMatrix = &(mRecordingStateStack.last().mMatrix); + else + mCurrentMatrix = &mRootMatrix; } //************************************** @@ -326,32 +366,43 @@ void PlatformGraphicsContextRecording::setStrokeThickness(float f) void PlatformGraphicsContextRecording::concatCTM(const AffineTransform& affine) { - mCurrentMatrix.preConcat(affine); + mCurrentMatrix->preConcat(affine); + onCurrentMatrixChanged(); appendStateOperation(new GraphicsOperation::ConcatCTM(affine)); } void PlatformGraphicsContextRecording::rotate(float angleInRadians) { float value = angleInRadians * (180.0f / 3.14159265f); - mCurrentMatrix.preRotate(SkFloatToScalar(value)); + mCurrentMatrix->preRotate(SkFloatToScalar(value)); + onCurrentMatrixChanged(); appendStateOperation(new GraphicsOperation::Rotate(angleInRadians)); } void PlatformGraphicsContextRecording::scale(const FloatSize& size) { - mCurrentMatrix.preScale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height())); + mCurrentMatrix->preScale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height())); + onCurrentMatrixChanged(); appendStateOperation(new GraphicsOperation::Scale(size)); } void PlatformGraphicsContextRecording::translate(float x, float y) { - mCurrentMatrix.preTranslate(SkFloatToScalar(x), SkFloatToScalar(y)); + mCurrentMatrix->preTranslate(SkFloatToScalar(x), SkFloatToScalar(y)); + onCurrentMatrixChanged(); appendStateOperation(new GraphicsOperation::Translate(x, y)); } const SkMatrix& PlatformGraphicsContextRecording::getTotalMatrix() { - return mCurrentMatrix; + // Each RecordingState tracks the delta from its "parent" SkMatrix + if (mRecordingStateStack.size()) { + SkMatrix total = mRootMatrix; + for (int i = 0; i < mRecordingStateStack.size(); i++) + total.preConcat(mRecordingStateStack[i].mMatrix); + return total; + } + return mRootMatrix; } //************************************** @@ -551,12 +602,14 @@ void PlatformGraphicsContextRecording::strokeRect(const FloatRect& rect, float l } void PlatformGraphicsContextRecording::appendDrawingOperation( - GraphicsOperation::Operation* operation, const FloatRect& bounds) + GraphicsOperation::Operation* operation, const FloatRect& untranslatedBounds) { - if (bounds.isEmpty()) { + if (untranslatedBounds.isEmpty()) { ALOGW("Empty bounds for %s(%s)!", operation->name(), operation->parameters().ascii().data()); return; } + SkRect bounds; + mCurrentMatrix->mapRect(&bounds, untranslatedBounds); if (mRecordingStateStack.size()) { RecordingState& state = mRecordingStateStack.last(); state.mHasDrawing = true; @@ -566,10 +619,13 @@ void PlatformGraphicsContextRecording::appendDrawingOperation( } if (!mOperationState) mOperationState = mRecording->recording()->getState(m_state); + if (!mOperationMatrix) + mOperationMatrix = mRecording->recording()->cloneMatrix(mRootMatrix); operation->m_state = mOperationState; + operation->m_matrix = mOperationMatrix; RecordingData* data = new RecordingData(operation, mRecording->recording()->m_nodeCount++); - float min[] = {bounds.x(), bounds.y()}; - float max[] = {bounds.maxX(), bounds.maxY()}; + float min[] = {bounds.fLeft, bounds.fTop}; + float max[] = {bounds.fRight, bounds.fBottom}; mRecording->recording()->m_tree.Insert(min, max, data); } @@ -583,4 +639,10 @@ void PlatformGraphicsContextRecording::appendStateOperation(GraphicsOperation::O } } +void PlatformGraphicsContextRecording::onCurrentMatrixChanged() +{ + if (mCurrentMatrix == &mRootMatrix) + mOperationMatrix = 0; +} + } // WebCore diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h index 95d4614..215aa84 100644 --- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h @@ -144,9 +144,11 @@ private: void appendDrawingOperation(GraphicsOperation::Operation* operation, const FloatRect& bounds); void appendStateOperation(GraphicsOperation::Operation* operation); + void onCurrentMatrixChanged(); SkPicture* mPicture; - SkMatrix mCurrentMatrix; + SkMatrix mRootMatrix; + SkMatrix* mCurrentMatrix; Recording* mRecording; class RecordingState { @@ -162,6 +164,7 @@ private: , mHasDrawing(other.mHasDrawing) , mHasClip(other.mHasClip) , mBounds(other.mBounds) + , mMatrix(other.mMatrix) {} void addBounds(const FloatRect& bounds) @@ -181,9 +184,11 @@ private: bool mHasDrawing; bool mHasClip; FloatRect mBounds; + SkMatrix mMatrix; }; Vector<RecordingState> mRecordingStateStack; State* mOperationState; + SkMatrix* mOperationMatrix; }; } |