diff options
-rw-r--r-- | core/fxge/skia/fx_skia_device.cpp | 179 |
1 files changed, 169 insertions, 10 deletions
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp index c9bc6f472f..eacfd69c93 100644 --- a/core/fxge/skia/fx_skia_device.cpp +++ b/core/fxge/skia/fx_skia_device.cpp @@ -153,6 +153,9 @@ void RgbByteOrderTransferBitmap(const CFX_RetainPtr<CFX_DIBitmap>& pBitmap, #endif // _SKIA_SUPPORT_PATHS_ #define SHOW_SKIA_PATH 0 // set to 1 to print the path contents +#if SHOW_SKIA_PATH +#define SHOW_SKIA_PATH_SHORTHAND 0 // set to 1 for abbreviated path contents +#endif #define DRAW_SKIA_CLIP 0 // set to 1 to draw a green rectangle around the clip #if SHOW_SKIA_PATH @@ -176,12 +179,16 @@ void DebugShowCanvasMatrix(const SkCanvas* canvas) { void DebugShowSkiaPath(const SkPath& path) { #if SHOW_SKIA_PATH +#if SHOW_SKIA_PATH_SHORTHAND + printf(" **\n"); +#else SkDynamicMemoryWStream stream; path.dump(&stream, false, false); std::unique_ptr<char, FxFreeDeleter> storage; storage.reset(FX_Alloc(char, stream.bytesWritten())); stream.copyTo(storage.get()); - printf("%s", storage.get()); + printf("%.*s", (int)stream.bytesWritten(), storage.get()); +#endif // SHOW_SKIA_PATH_SHORTHAND #endif // SHOW_SKIA_PATH } @@ -923,20 +930,20 @@ class SkiaState { Dump(__func__); int count = m_commands.count(); if (m_commandIndex < count - 1) { - if (Clip::kSave == m_commands[m_commandIndex + 1]) { + if (Clip::kSave == m_commands[m_commandIndex]) { ++m_commandIndex; return true; } Flush(); AdjustClip(m_commandIndex); - m_commands[++m_commandIndex] = Clip::kSave; + m_commands[m_commandIndex] = Clip::kSave; m_clips[m_commandIndex] = m_skEmptyPath; } else { AdjustClip(m_commandIndex); m_commands.push(Clip::kSave); m_clips.push_back(m_skEmptyPath); - ++m_commandIndex; } + ++m_commandIndex; return true; } @@ -1071,34 +1078,177 @@ class SkiaState { void Dump(const char* where) const { #if SHOW_SKIA_PATH - printf("\n%s\nSkia Save Count %d:\n", where, - m_pDriver->m_pCanvas->getSaveCount()); + if (m_debugDisable) + return; + printf( + "\n%s\nSkia Save Count %d Agg Save Count %d" + " Cache Save Count %d\n", + where, m_pDriver->m_pCanvas->getSaveCount(), + (int)m_pDriver->m_StateStack.size(), m_commandIndex); printf("Cache:\n"); +#if SHOW_SKIA_PATH_SHORTHAND + bool dumpedPath = false; +#endif for (int index = 0; index < m_commands.count(); ++index) { +#if SHOW_SKIA_PATH_SHORTHAND + if (Clip::kSave == m_commands[index] && dumpedPath) { + printf("\n"); + dumpedPath = false; + } +#endif DumpPrefix(index); switch (m_commands[index]) { case Clip::kSave: printf("Save %d\n", ++m_debugSaveCounter); break; case Clip::kPath: +#if SHOW_SKIA_PATH_SHORTHAND + printf("*"); + dumpedPath = true; +#else m_clips[index].dump(); +#endif break; default: printf("unknown\n"); } } +#if SHOW_SKIA_PATH_SHORTHAND + if (dumpedPath) + printf("\n"); +#endif DumpEndPrefix(); -#endif // SHOW_SKIA_PATH -#ifdef SK_DEBUG int skCanvasSaveCount = m_pDriver->m_pCanvas->getSaveCount(); int cacheSaveCount = 1; SkASSERT(m_clipIndex <= m_commands.count()); for (int index = 0; index < m_clipIndex; ++index) cacheSaveCount += Clip::kSave == m_commands[index]; SkASSERT(skCanvasSaveCount == cacheSaveCount); -#endif +#endif // SHOW_SKIA_PATH + } + + void DebugCheckClip() { +#if SHOW_SKIA_PATH + if (m_debugDisable) + return; + int aggSaveCount = 0; + FX_RECT last; + bool foundLast = false; + for (int index = 0; index < (int)m_pDriver->m_StateStack.size(); ++index) { + if (!m_pDriver->m_StateStack[index]) { + continue; + } + if (m_pDriver->m_StateStack[index]->GetType() != CFX_ClipRgn::RectI) { + aggSaveCount += 1; + foundLast = false; + continue; + } + if (!foundLast || memcmp(&last, &m_pDriver->m_StateStack[index]->GetBox(), + sizeof(FX_RECT))) { + aggSaveCount += 1; + foundLast = true; + last = m_pDriver->m_StateStack[index]->GetBox(); + } + } + if (m_pDriver->m_pClipRgn) { + CFX_ClipRgn::ClipType clipType = m_pDriver->m_pClipRgn->GetType(); + if (clipType != CFX_ClipRgn::RectI || !foundLast || + memcmp(&last, &m_pDriver->m_pClipRgn->GetBox(), sizeof(FX_RECT))) { + aggSaveCount += 1; + } + } + int cacheSaveCount = 0; + SkASSERT(m_clipIndex <= m_commands.count()); + bool newPath = false; + for (int index = 0; index < m_commandIndex; ++index) { + if (Clip::kSave == m_commands[index]) { + newPath = true; + } else if (newPath) { + ++cacheSaveCount; + newPath = false; + } + } + if (aggSaveCount != cacheSaveCount) { + DumpClipStacks(); + SkASSERT(0); + return; + } + for (int aggIndex = 0; aggIndex < (int)m_pDriver->m_StateStack.size(); + ++aggIndex) { + if (!m_pDriver->m_StateStack[aggIndex]) + continue; + if (m_pDriver->m_StateStack[aggIndex]->GetType() != CFX_ClipRgn::RectI) + continue; + const FX_RECT& aggRect = m_pDriver->m_StateStack[aggIndex]->GetBox(); + SkRect skRect = SkRect::MakeLTRB(aggRect.left, aggRect.top, aggRect.right, + aggRect.bottom); + bool foundMatch = false; + for (int skIndex = 0; skIndex < m_commandIndex; ++skIndex) { + if (Clip::kPath != m_commands[skIndex]) + continue; + const SkPath& clip = m_clips[skIndex]; + SkRect bounds; + if (!clip.isRect(&bounds)) + continue; + bounds.roundOut(&bounds); + if (skRect == bounds) { + foundMatch = true; + break; + } + } + if (!foundMatch) { + DumpClipStacks(); + SkASSERT(0); + } + } +#endif // SHOW_SKIA_PATH } +#if SHOW_SKIA_PATH + void DumpClipStacks() const { + if (m_debugDisable) + return; + printf("\ncache\n"); + for (int index = 0; index < m_commandIndex; ++index) { + DumpPrefix(index); + switch (m_commands[index]) { + case Clip::kSave: + printf("Save\n"); + break; + case Clip::kPath: + m_clips[index].dump(); + break; + default: + printf("unknown\n"); + } + } + printf("\nagg\n"); + for (int index = 0; index < (int)m_pDriver->m_StateStack.size(); ++index) { + if (!m_pDriver->m_StateStack[index]) { + printf("null\n"); + continue; + } + CFX_ClipRgn::ClipType clipType = + m_pDriver->m_StateStack[index]->GetType(); + const FX_RECT& box = m_pDriver->m_StateStack[index]->GetBox(); + printf("stack rect: %d,%d,%d,%d mask=%s\n", box.left, box.top, box.right, + box.bottom, + CFX_ClipRgn::MaskF == clipType + ? "1" + : CFX_ClipRgn::RectI == clipType ? "0" : "?"); + } + if (m_pDriver->m_pClipRgn) { + const FX_RECT& box = m_pDriver->m_pClipRgn->GetBox(); + CFX_ClipRgn::ClipType clipType = m_pDriver->m_pClipRgn->GetType(); + printf("clip rect: %d,%d,%d,%d mask=%s\n", box.left, box.top, box.right, + box.bottom, + CFX_ClipRgn::MaskF == clipType + ? "1" + : CFX_ClipRgn::RectI == clipType ? "0" : "?"); + } + } +#endif // SHOW_SKIA_PATH + private: SkTArray<SkPath> m_clips; // stack of clips that may be reused SkTDArray<Clip> m_commands; // stack of clip-related commands @@ -1125,6 +1275,7 @@ class SkiaState { bool m_groupKnockout; bool m_debugDisable; // turn off cache for debugging #if SHOW_SKIA_PATH + public: mutable int m_debugSaveCounter; static int m_debugInitCounter; #endif @@ -1355,10 +1506,14 @@ int CFX_SkiaDeviceDriver::GetDeviceCaps(int caps_id) const { } void CFX_SkiaDeviceDriver::SaveState() { + m_pCache->DebugCheckClip(); if (!m_pCache->ClipSave()) m_pCanvas->save(); #ifdef _SKIA_SUPPORT_PATHS_ +#if SHOW_SKIA_PATH + printf("SaveState %zd\n", m_StateStack.size()); +#endif std::unique_ptr<CFX_ClipRgn> pClip; if (m_pClipRgn) pClip = pdfium::MakeUnique<CFX_ClipRgn>(*m_pClipRgn); @@ -1376,12 +1531,15 @@ void CFX_SkiaDeviceDriver::RestoreState(bool bKeepSaved) { if (m_pCache->IsEmpty()) return; #endif - if (!m_pCache->ClipRestore()) m_pCanvas->restore(); if (bKeepSaved && !m_pCache->ClipSave()) m_pCanvas->save(); #ifdef _SKIA_SUPPORT_PATHS_ +#if SHOW_SKIA_PATH + printf("RestoreState %zd %s\n", m_StateStack.size(), + bKeepSaved ? "bKeepSaved" : ""); +#endif if (bKeepSaved) { if (m_StateStack.back()) m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(*m_StateStack.back()); @@ -1389,6 +1547,7 @@ void CFX_SkiaDeviceDriver::RestoreState(bool bKeepSaved) { m_pClipRgn = std::move(m_StateStack.back()); m_StateStack.pop_back(); } + m_pCache->DebugCheckClip(); #endif // _SKIA_SUPPORT_PATHS_ } |