From 9bb47cf0ffcf8a802c0126fa3ee2b5ee7287959b Mon Sep 17 00:00:00 2001 From: Brian Osman Date: Thu, 26 Apr 2018 15:55:00 -0400 Subject: Add perspective support (rect to rect) to Viewer Change-Id: I312d5b3e6b7f37a3a7bfd5561bcdb31b43e207b8 Reviewed-on: https://skia-review.googlesource.com/123934 Commit-Queue: Brian Osman Commit-Queue: Greg Daniel Commit-Queue: Ben Wagner Reviewed-by: Greg Daniel Reviewed-by: Ben Wagner Auto-Submit: Brian Osman --- tools/viewer/Viewer.cpp | 87 +++++++++++++++++++++++++++++++++++++++++++++++-- tools/viewer/Viewer.h | 3 ++ 2 files changed, 88 insertions(+), 2 deletions(-) (limited to 'tools/viewer') diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp index 04426ffc7e..3411e5684b 100644 --- a/tools/viewer/Viewer.cpp +++ b/tools/viewer/Viewer.cpp @@ -178,6 +178,7 @@ Viewer::Viewer(int argc, char** argv, void* platformData) , fZoomLevel(0.0f) , fRotation(0.0f) , fGestureDevice(GestureDevice::kNone) + , fPerspective(false) , fTileCnt(0) , fThreadCnt(0) { @@ -494,6 +495,10 @@ Viewer::Viewer(int argc, char** argv, void* platformData) this->listNames(); } + fPerspectivePoints[0].set(0, 0); + fPerspectivePoints[1].set(1, 0); + fPerspectivePoints[2].set(0, 1); + fPerspectivePoints[3].set(1, 1); fAnimTimer.run(); auto gamutImage = GetResourceAsImage("images/gamut.png"); @@ -878,6 +883,21 @@ SkMatrix Viewer::computePreTouchMatrix() { : SK_Scalar1 + fZoomLevel; m.preScale(zoomScale, zoomScale); m.preRotate(fRotation); + + if (fPerspective) { + SkScalar w = fWindow->width(), h = fWindow->height(); + SkPoint orthoPts[4] = { { 0, 0 }, { w, 0 }, { 0, h }, { w, h } }; + SkPoint perspPts[4] = { + { fPerspectivePoints[0].fX * w, fPerspectivePoints[0].fY * h }, + { fPerspectivePoints[1].fX * w, fPerspectivePoints[1].fY * h }, + { fPerspectivePoints[2].fX * w, fPerspectivePoints[2].fY * h }, + { fPerspectivePoints[3].fX * w, fPerspectivePoints[3].fY * h } + }; + SkMatrix persp; + persp.setPolyToPoly(orthoPts, perspPts, 4); + m.preConcat(persp); + } + return m; } @@ -1204,7 +1224,6 @@ static void ImGui_Primaries(SkColorSpacePrimaries* primaries, SkPaint* gamutPain // Magic numbers are pixel locations of the origin and upper-right corner. drawList->AddImage(gamutPaint, pos, ImVec2(pos.x + size.x, pos.y + size.y), ImVec2(242, 61), ImVec2(1897, 1922)); - ImVec2 endPos = ImGui::GetCursorPos(); // Primary markers ImVec2 r = ImGui_DragPrimary("R", &primaries->fRX, &primaries->fRY, pos, size); @@ -1220,7 +1239,65 @@ static void ImGui_Primaries(SkColorSpacePrimaries* primaries, SkPaint* gamutPain drawList->AddTriangle(r, g, b, 0xFFFFFFFF); // Re-position cursor immediate after the diagram for subsequent controls - ImGui::SetCursorPos(endPos); + ImGui::SetCursorScreenPos(ImVec2(pos.x, pos.y + size.y)); +} + +static ImVec2 ImGui_DragPoint(const char* label, SkPoint* p, + const ImVec2& pos, const ImVec2& size, bool* dragging) { + // Transform points ([0, 0] - [1.0, 1.0]) to screen coords + ImVec2 center(pos.x + p->fX * size.x, pos.y + p->fY * size.y); + + // Invisible 10x10 button + ImGui::SetCursorScreenPos(ImVec2(center.x - 5, center.y - 5)); + ImGui::InvisibleButton(label, ImVec2(10, 10)); + + if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { + ImGuiIO& io = ImGui::GetIO(); + // Normalized mouse position, relative to our gamut box + ImVec2 mousePosXY((io.MousePos.x - pos.x) / size.x, (io.MousePos.y - pos.y) / size.y); + // Clamp to edge of box + p->fX = SkTPin(mousePosXY.x, 0.0f, 1.0f); + p->fY = SkTPin(mousePosXY.y, 0.0f, 1.0f); + *dragging = true; + } + + // Return screen coordinates for the caller. We could just return center here, but we'd have + // one frame of lag during drag. + return ImVec2(pos.x + p->fX * size.x, pos.y + p->fY * size.y); +} + +static bool ImGui_DragQuad(SkPoint* pts) { + ImDrawList* drawList = ImGui::GetWindowDrawList(); + + // Fit our image/canvas to the available width, and scale the height to maintain aspect ratio. + float canvasWidth = SkTMax(ImGui::GetContentRegionAvailWidth(), 50.0f); + ImVec2 size = ImVec2(canvasWidth, canvasWidth); + ImVec2 pos = ImGui::GetCursorScreenPos(); + + // Background rectangle + drawList->AddRectFilled(pos, ImVec2(pos.x + size.x, pos.y + size.y), IM_COL32(0, 0, 0, 128)); + + // Corner markers + bool dragging = false; + ImVec2 tl = ImGui_DragPoint("TL", pts + 0, pos, size, &dragging); + ImVec2 tr = ImGui_DragPoint("TR", pts + 1, pos, size, &dragging); + ImVec2 bl = ImGui_DragPoint("BL", pts + 2, pos, size, &dragging); + ImVec2 br = ImGui_DragPoint("BR", pts + 3, pos, size, &dragging); + + // Draw markers and quad + drawList->AddCircle(tl, 5.0f, 0xFFFFFFFF); + drawList->AddCircle(tr, 5.0f, 0xFFFFFFFF); + drawList->AddCircle(bl, 5.0f, 0xFFFFFFFF); + drawList->AddCircle(br, 5.0f, 0xFFFFFFFF); + drawList->AddLine(tl, tr, 0xFFFFFFFF); + drawList->AddLine(tr, br, 0xFFFFFFFF); + drawList->AddLine(br, bl, 0xFFFFFFFF); + drawList->AddLine(bl, tl, 0xFFFFFFFF); + + ImGui::SetCursorScreenPos(ImVec2(pos.x, pos.y + size.y)); + ImGui::Spacing(); + + return dragging; } void Viewer::drawImGui() { @@ -1356,6 +1433,12 @@ void Viewer::drawImGui() { this->preTouchMatrixChanged(); paramsChanged = true; } + if (ImGui::Checkbox("Perspective", &fPerspective)) { + this->preTouchMatrixChanged(); + } + if (ImGui_DragQuad(fPerspectivePoints)) { + this->preTouchMatrixChanged(); + } } if (ImGui::CollapsingHeader("Paint")) { diff --git a/tools/viewer/Viewer.h b/tools/viewer/Viewer.h index 25cbed656c..be35a88525 100644 --- a/tools/viewer/Viewer.h +++ b/tools/viewer/Viewer.h @@ -158,6 +158,9 @@ private: // identity unless the window initially scales the content to fit the screen. SkMatrix fDefaultMatrix; + bool fPerspective; + SkPoint fPerspectivePoints[4]; + SkTArray> fDeferredActions; Json::Value fAllSlideNames; // cache all slide names for fast updateUIState -- cgit v1.2.3