Pixel zoomer in viewer
Made it a separate ImGui window (rather than part of the debug window).
Bring it up with 'z'. Draggable/resizable. Variable zoom scale. Enjoy.
BUG=skia:
Change-Id: I949ab398126c892c8d353aaebcc8403765f42841
Reviewed-on: https://skia-review.googlesource.com/8357
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp
index e935563..1d5e033 100644
--- a/tools/viewer/Viewer.cpp
+++ b/tools/viewer/Viewer.cpp
@@ -173,6 +173,8 @@
, fRefresh(false)
, fShowImGuiDebugWindow(false)
, fShowImGuiTestWindow(false)
+ , fShowZoomWindow(false)
+ , fLastImage(nullptr)
, fBackendType(sk_app::Window::kNativeGL_BackendType)
, fColorType(kN32_SkColorType)
, fColorSpace(nullptr)
@@ -225,6 +227,10 @@
this->fShowImGuiTestWindow = !this->fShowImGuiTestWindow;
fWindow->inval();
});
+ fCommands.addCommand('z', "GUI", "Toggle zoom window", [this]() {
+ this->fShowZoomWindow = !this->fShowZoomWindow;
+ fWindow->inval();
+ });
fCommands.addCommand('s', "Overlays", "Toggle stats display", [this]() {
this->fDisplayStats = !this->fDisplayStats;
fWindow->inval();
@@ -351,7 +357,14 @@
io.Fonts->GetTexDataAsAlpha8(&pixels, &w, &h);
SkImageInfo info = SkImageInfo::MakeA8(w, h);
SkPixmap pmap(info, pixels, info.minRowBytes());
- fImGuiFontImage = SkImage::MakeFromRaster(pmap, nullptr, nullptr);
+ SkMatrix localMatrix = SkMatrix::MakeScale(1.0f / w, 1.0f / h);
+ auto fontImage = SkImage::MakeFromRaster(pmap, nullptr, nullptr);
+ auto fontShader = fontImage->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
+ &localMatrix);
+ fImGuiFontPaint.setShader(fontShader);
+ fImGuiFontPaint.setColor(SK_ColorWHITE);
+ fImGuiFontPaint.setFilterQuality(kLow_SkFilterQuality);
+ io.Fonts->TexID = &fImGuiFontPaint;
fWindow->show();
}
@@ -559,10 +572,11 @@
// By default, we render directly into the window's surface/canvas
SkCanvas* slideCanvas = canvas;
+ fLastImage.reset();
- // ... but if we're in F16, or the gamut isn't sRGB, we need to render offscreen
+ // If we're in F16, or the gamut isn't sRGB, or we're zooming, we need to render offscreen
sk_sp<SkSurface> offscreenSurface = nullptr;
- if (kRGBA_F16_SkColorType == fColorType ||
+ if (kRGBA_F16_SkColorType == fColorType || fShowZoomWindow ||
(fColorSpace && fColorSpace != SkColorSpace::MakeSRGB())) {
SkImageInfo info = SkImageInfo::Make(fWindow->width(), fWindow->height(), fColorType,
kPremul_SkAlphaType, fColorSpace);
@@ -586,12 +600,12 @@
// If we rendered offscreen, snap an image and push the results to the window's canvas
if (offscreenSurface) {
- auto slideImage = offscreenSurface->makeImageSnapshot();
+ fLastImage = offscreenSurface->makeImageSnapshot();
// Tag the image with the sRGB gamut, so no further color space conversion happens
sk_sp<SkColorSpace> cs = (kRGBA_F16_SkColorType == fColorType)
? SkColorSpace::MakeSRGBLinear() : SkColorSpace::MakeSRGB();
- auto retaggedImage = SkImageMakeRasterCopyAndAssignColorSpace(slideImage.get(), cs.get());
+ auto retaggedImage = SkImageMakeRasterCopyAndAssignColorSpace(fLastImage.get(), cs.get());
canvas->drawImage(retaggedImage, 0, 0);
}
@@ -745,6 +759,30 @@
ImGui::End();
}
+ SkPaint zoomImagePaint;
+ if (fShowZoomWindow && fLastImage) {
+ if (ImGui::Begin("Zoom", &fShowZoomWindow, ImVec2(200, 200))) {
+ static int zoomFactor = 4;
+ ImGui::SliderInt("Scale", &zoomFactor, 1, 16);
+
+ zoomImagePaint.setShader(fLastImage->makeShader(SkShader::kClamp_TileMode,
+ SkShader::kClamp_TileMode));
+ zoomImagePaint.setColor(SK_ColorWHITE);
+
+ // Zoom by shrinking the corner UVs towards the mouse cursor
+ ImVec2 mousePos = ImGui::GetMousePos();
+ ImVec2 avail = ImGui::GetContentRegionAvail();
+
+ ImVec2 zoomHalfExtents = ImVec2((avail.x * 0.5f) / zoomFactor,
+ (avail.y * 0.5f) / zoomFactor);
+ ImGui::Image(&zoomImagePaint, avail,
+ ImVec2(mousePos.x - zoomHalfExtents.x, mousePos.y - zoomHalfExtents.y),
+ ImVec2(mousePos.x + zoomHalfExtents.x, mousePos.y + zoomHalfExtents.y));
+ }
+
+ ImGui::End();
+ }
+
// This causes ImGui to rebuild vertex/index data based on all immediate-mode commands
// (widgets, etc...) that have been issued
ImGui::Render();
@@ -754,14 +792,6 @@
SkTDArray<SkPoint> pos;
SkTDArray<SkPoint> uv;
SkTDArray<SkColor> color;
- SkPaint imguiPaint;
- imguiPaint.setColor(SK_ColorWHITE);
- SkMatrix localMatrix = SkMatrix::MakeScale(1.0f / fImGuiFontImage->width(),
- 1.0f / fImGuiFontImage->height());
- imguiPaint.setShader(fImGuiFontImage->makeShader(SkShader::kClamp_TileMode,
- SkShader::kClamp_TileMode,
- &localMatrix));
- imguiPaint.setFilterQuality(kLow_SkFilterQuality);
for (int i = 0; i < drawData->CmdListsCount; ++i) {
const ImDrawList* drawList = drawData->CmdLists[i];
@@ -787,13 +817,16 @@
if (drawCmd->UserCallback) {
drawCmd->UserCallback(drawList, drawCmd);
} else {
+ SkPaint* paint = static_cast<SkPaint*>(drawCmd->TextureId);
+ SkASSERT(paint);
+
canvas->save();
canvas->clipRect(SkRect::MakeLTRB(drawCmd->ClipRect.x, drawCmd->ClipRect.y,
drawCmd->ClipRect.z, drawCmd->ClipRect.w));
canvas->drawVertices(SkCanvas::kTriangles_VertexMode, drawList->VtxBuffer.size(),
pos.begin(), uv.begin(), color.begin(),
drawList->IdxBuffer.begin() + indexOffset, drawCmd->ElemCount,
- imguiPaint);
+ *paint);
indexOffset += drawCmd->ElemCount;
canvas->restore();
}
diff --git a/tools/viewer/Viewer.h b/tools/viewer/Viewer.h
index 9499c6c..74d3f06 100644
--- a/tools/viewer/Viewer.h
+++ b/tools/viewer/Viewer.h
@@ -60,10 +60,13 @@
bool fDisplayStats;
bool fRefresh; // whether to continuously refresh for measuring render time
- sk_sp<SkImage> fImGuiFontImage;
+ SkPaint fImGuiFontPaint;
bool fShowImGuiDebugWindow;
bool fShowImGuiTestWindow;
+ bool fShowZoomWindow;
+ sk_sp<SkImage> fLastImage;
+
sk_app::Window::BackendType fBackendType;
// Color properties for slide rendering