blob: a1686cd36bf656c403ecb2308902298025e53e73 [file] [log] [blame]
// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/debug/backend/overlay_agent.h"
#include "cobalt/math/clamp.h"
#include "cobalt/math/rect_f.h"
#include "cobalt/render_tree/brush.h"
#include "cobalt/render_tree/color_rgba.h"
#include "cobalt/render_tree/composition_node.h"
#include "cobalt/render_tree/rect_node.h"
namespace cobalt {
namespace debug {
namespace backend {
using base::Value;
using math::Clamp;
using render_tree::ColorRGBA;
namespace {
// Returns the float value of a param, or 0.0 if undefined or non-numeric.
float GetFloatParam(const Value* params, base::StringPiece key) {
if (!params || !params->is_dict()) return 0.0f;
const Value* v = params->FindKey(key);
if (!v || !(v->is_double() || v->is_int())) return 0.0f;
return static_cast<float>(v->GetDouble());
}
// Returns an RGBA color defined by a param, or transparent if undefined.
ColorRGBA RenderColor(const Value* params) {
float r = GetFloatParam(params, "r") / 255.0f;
float g = GetFloatParam(params, "g") / 255.0f;
float b = GetFloatParam(params, "b") / 255.0f;
float a = GetFloatParam(params, "a");
return ColorRGBA(Clamp(r, 0.0f, 1.0f), Clamp(g, 0.0f, 1.0f),
Clamp(b, 0.0f, 1.0f), Clamp(a, 0.0f, 1.0f));
}
// Returns a rectangle to render according to the params for the DevTools
// "Overlay.highlightRect" command.
// https://chromedevtools.github.io/devtools-protocol/tot/Overlay#method-highlightRect
scoped_refptr<render_tree::RectNode> RenderHighlightRect(const Value* params) {
float x = GetFloatParam(params, "x");
float y = GetFloatParam(params, "y");
float width = GetFloatParam(params, "width");
float height = GetFloatParam(params, "height");
ColorRGBA color(RenderColor(params->FindKey("color")));
const Value* outline_param = params->FindKey("outlineColor");
ColorRGBA outline_color(RenderColor(outline_param));
float outline_width = outline_param ? 1.0f : 0.0f;
return base::MakeRefCounted<render_tree::RectNode>(
math::RectF(x, y, width, height),
std::make_unique<render_tree::SolidColorBrush>(color),
std::make_unique<render_tree::Border>(render_tree::BorderSide(
outline_width, render_tree::kBorderStyleSolid, outline_color)));
}
} // namespace
OverlayAgent::OverlayAgent(DebugDispatcher* dispatcher,
std::unique_ptr<RenderLayer> render_layer)
: AgentBase("Overlay", "overlay_agent.js", dispatcher),
render_layer_(std::move(render_layer)) {
DCHECK(render_layer_);
commands_["highlightNode"] =
base::Bind(&OverlayAgent::HighlightNode, base::Unretained(this));
commands_["highlightRect"] =
base::Bind(&OverlayAgent::HighlightRect, base::Unretained(this));
commands_["hideHighlight"] =
base::Bind(&OverlayAgent::HideHighlight, base::Unretained(this));
commands_["setShowViewportSizeOnResize"] = base::Bind(
&OverlayAgent::SetShowViewportSizeOnResize, base::Unretained(this));
}
void OverlayAgent::HighlightNode(Command command) {
if (!EnsureEnabled(&command)) return;
// Use the injected JavaScript helper to get the rectangles to highlight for
// the specified node.
JSONObject rects_response = dispatcher_->RunScriptCommand(
"Overlay._highlightNodeRects", command.GetParams());
const Value* highlight_rects =
rects_response->FindPath({"result", "highlightRects"});
if (!highlight_rects) {
command.SendErrorResponse(Command::kInvalidParams,
"Can't get node highlights.");
return;
}
// Render all the highlight rects as children of a CompositionNode.
render_tree::CompositionNode::Builder builder;
for (const Value& rect_params : highlight_rects->GetList()) {
builder.AddChild(RenderHighlightRect(&rect_params));
}
render_layer_->SetFrontLayer(
base::MakeRefCounted<render_tree::CompositionNode>(builder));
command.SendResponse();
}
void OverlayAgent::HighlightRect(Command command) {
if (!EnsureEnabled(&command)) return;
JSONObject params = JSONParse(command.GetParams());
render_layer_->SetFrontLayer(RenderHighlightRect(params.get()));
command.SendResponse();
}
void OverlayAgent::HideHighlight(Command command) {
if (!EnsureEnabled(&command)) return;
render_layer_->SetFrontLayer(scoped_refptr<render_tree::Node>());
command.SendResponse();
}
void OverlayAgent::SetShowViewportSizeOnResize(Command command) {
// NO-OP implementation needed to prevent a frontend runtime exception when
// Overlay settings are restored after the Performance panel stops tracing.
command.SendResponse();
}
} // namespace backend
} // namespace debug
} // namespace cobalt