summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCary Clark <caryclark@google.com>2017-04-12 11:53:32 -0400
committerChromium commit bot <commit-bot@chromium.org>2017-04-12 17:22:07 +0000
commitb333c9ec415c132451f4a10487b84f91124d08e8 (patch)
tree747f667282154638e5cd705ab53b4f0cdb329443
parent445831ebcec3426f5642d32336d654fb391ca07a (diff)
downloadpdfium-b333c9ec415c132451f4a10487b84f91124d08e8.tar.xz
Clip stack management was off by one.
To help find future bugs, add printf and checking to see that the skia clip stack and the pdfium clip stack are in sync. Bug: 705783,795821 Change-Id: I3ed39cbe2514ab18e5bee6eb363cc2d0f042bff5 Reviewed-on: https://pdfium-review.googlesource.com/4090 Reviewed-by: dsinclair <dsinclair@chromium.org> Commit-Queue: dsinclair <dsinclair@chromium.org>
-rw-r--r--core/fxge/skia/fx_skia_device.cpp179
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_
}