static bool verify_query(SkRect query, SkRect rects[], SkTDArray<int>& found) { SkTDArray<int> expected; // manually intersect with every rectangle for (int i = 0; i < NUM_RECTS; ++i) { if (SkRect::Intersects(query, rects[i])) { expected.push_back(i); } } if (expected.count() != found.count()) { return false; } if (0 == expected.count()) { return true; } return found == expected; }
void ImGuiLayer::onPaint(SkSurface* surface) { // This causes ImGui to rebuild vertex/index data based on all immediate-mode commands // (widgets, etc...) that have been issued ImGui::Render(); // Then we fetch the most recent data, and convert it so we can render with Skia const ImDrawData* drawData = ImGui::GetDrawData(); SkTDArray<SkPoint> pos; SkTDArray<SkPoint> uv; SkTDArray<SkColor> color; auto canvas = surface->getCanvas(); for (int i = 0; i < drawData->CmdListsCount; ++i) { const ImDrawList* drawList = drawData->CmdLists[i]; // De-interleave all vertex data (sigh), convert to Skia types pos.rewind(); uv.rewind(); color.rewind(); for (int j = 0; j < drawList->VtxBuffer.size(); ++j) { const ImDrawVert& vert = drawList->VtxBuffer[j]; pos.push_back(SkPoint::Make(vert.pos.x, vert.pos.y)); uv.push_back(SkPoint::Make(vert.uv.x, vert.uv.y)); color.push_back(vert.col); } // ImGui colors are RGBA SkSwapRB(color.begin(), color.begin(), color.count()); int indexOffset = 0; // Draw everything with canvas.drawVertices... for (int j = 0; j < drawList->CmdBuffer.size(); ++j) { const ImDrawCmd* drawCmd = &drawList->CmdBuffer[j]; SkAutoCanvasRestore acr(canvas, true); // TODO: Find min/max index for each draw, so we know how many vertices (sigh) if (drawCmd->UserCallback) { drawCmd->UserCallback(drawList, drawCmd); } else { intptr_t idIndex = (intptr_t)drawCmd->TextureId; if (idIndex < fSkiaWidgetFuncs.count()) { // Small image IDs are actually indices into a list of callbacks. We directly // examing the vertex data to deduce the image rectangle, then reconfigure the // canvas to be clipped and translated so that the callback code gets to use // Skia to render a widget in the middle of an ImGui panel. ImDrawIdx rectIndex = drawList->IdxBuffer[indexOffset]; SkPoint tl = pos[rectIndex], br = pos[rectIndex + 2]; canvas->clipRect(SkRect::MakeLTRB(tl.fX, tl.fY, br.fX, br.fY)); canvas->translate(tl.fX, tl.fY); fSkiaWidgetFuncs[idIndex](canvas); } else { SkPaint* paint = static_cast<SkPaint*>(drawCmd->TextureId); SkASSERT(paint); canvas->clipRect(SkRect::MakeLTRB(drawCmd->ClipRect.x, drawCmd->ClipRect.y, drawCmd->ClipRect.z, drawCmd->ClipRect.w)); auto vertices = SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode, drawList->VtxBuffer.size(), pos.begin(), uv.begin(), color.begin(), drawCmd->ElemCount, drawList->IdxBuffer.begin() + indexOffset); canvas->drawVertices(vertices, SkBlendMode::kModulate, *paint); } indexOffset += drawCmd->ElemCount; } } } fSkiaWidgetFuncs.reset(); }