Commit 6a2cccb9 authored by Christopher Grant's avatar Christopher Grant Committed by Commit Bot

VR: Support non-multiline text

Text elements can now default to multiline, but can be configured as
single-line, to truncate rather than grow the texture vertically.

Along the way, remove a field width parameter from the Text constructor.  This
value needs to match the element size, and should be pulled from element size
rather than explicitly set to match.

BUG=
TBR=vollick@chromium.org

Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: I8a0e48b1efb3b562e9a8f0037e9718020bcfc01b
Reviewed-on: https://chromium-review.googlesource.com/796710
Commit-Queue: Christopher Grant <cjgrant@chromium.org>
Reviewed-by: default avatarIan Vollick <vollick@chromium.org>
Reviewed-by: default avatarBiao She <bshe@chromium.org>
Cr-Commit-Position: refs/heads/master@{#520578}
parent d9c512d4
......@@ -231,6 +231,7 @@ test("vr_common_unittests") {
"elements/scaled_depth_adjuster_unittest.cc",
"elements/shadow_unittest.cc",
"elements/spinner_unittest.cc",
"elements/text_unittest.cc",
"elements/throbber_unittest.cc",
"elements/transient_element_unittest.cc",
"elements/ui_element_iterator_unittest.cc",
......
......@@ -17,8 +17,7 @@ namespace vr {
class TextTexture : public UiTexture {
public:
TextTexture(float font_height, float text_width)
: font_height_(font_height), text_width_(text_width) {}
explicit TextTexture(float font_height) : font_height_(font_height) {}
~TextTexture() override {}
void SetText(const base::string16& text) { SetAndDirty(&text_, text); }
......@@ -29,6 +28,12 @@ class TextTexture : public UiTexture {
SetAndDirty(&alignment_, alignment);
}
void SetMultiLine(bool multiline) { SetAndDirty(&multiline_, multiline); }
void SetTextWidth(float width) { SetAndDirty(&text_width_, width); }
int rendered_lines() { return rendered_lines_; }
private:
gfx::Size GetPreferredTextureSize(int width) const override {
return gfx::Size(width, width);
......@@ -40,22 +45,22 @@ class TextTexture : public UiTexture {
gfx::SizeF size_;
base::string16 text_;
// These widths are in meters.
float font_height_;
float text_width_;
// These dimensions are in meters.
float font_height_ = 0;
float text_width_ = 0;
TextAlignment alignment_ = kTextAlignmentCenter;
bool multiline_ = true;
SkColor color_ = SK_ColorBLACK;
// The number of lines generated in the last draw operation.
int rendered_lines_ = 0;
DISALLOW_COPY_AND_ASSIGN(TextTexture);
};
Text::Text(int maximum_width_pixels,
float font_height_meters,
float text_width_meters)
Text::Text(int maximum_width_pixels, float font_height_meters)
: TexturedElement(maximum_width_pixels),
texture_(base::MakeUnique<TextTexture>(font_height_meters,
text_width_meters)) {}
texture_(base::MakeUnique<TextTexture>(font_height_meters)) {}
Text::~Text() {}
void Text::SetText(const base::string16& text) {
......@@ -70,6 +75,18 @@ void Text::SetTextAlignment(UiTexture::TextAlignment alignment) {
texture_->SetAlignment(alignment);
}
void Text::SetMultiLine(bool multiline) {
texture_->SetMultiLine(multiline);
}
void Text::OnSetSize(gfx::SizeF size) {
texture_->SetTextWidth(size.width());
}
int Text::NumRenderedLinesForTest() const {
return texture_->rendered_lines();
}
UiTexture* Text::GetTexture() const {
return texture_.get();
}
......@@ -83,19 +100,28 @@ void TextTexture::Draw(SkCanvas* sk_canvas, const gfx::Size& texture_size) {
float pixels_per_meter = texture_size.width() / text_width_;
int pixel_font_height = static_cast<int>(font_height_ * pixels_per_meter);
GetDefaultFontList(pixel_font_height, text_, &fonts);
gfx::Rect text_bounds(texture_size.width(), 0);
gfx::Rect text_bounds(texture_size.width(),
multiline_ ? 0 : texture_size.height());
std::vector<std::unique_ptr<gfx::RenderText>> lines =
// TODO(vollick): if this subsumes all text, then we should probably move
// this function into this class.
PrepareDrawStringRect(text_, fonts, color_, &text_bounds, alignment_,
kWrappingBehaviorWrap);
PrepareDrawStringRect(
text_, fonts, color_, &text_bounds, alignment_,
multiline_ ? kWrappingBehaviorWrap : kWrappingBehaviorNoWrap);
// Draw the text.
for (auto& render_text : lines)
render_text->Draw(canvas);
// Note, there is no padding here whatsoever.
size_ = gfx::SizeF(text_bounds.size());
rendered_lines_ = lines.size();
}
UiTexture* Text::GetTextureForTest() const {
return texture_.get();
}
} // namespace vr
......@@ -17,15 +17,20 @@ class TextTexture;
class Text : public TexturedElement {
public:
Text(int maximum_width_pixels,
float font_height_meters,
float text_width_meters);
Text(int maximum_width_pixels, float font_height_meters);
~Text() override;
void SetText(const base::string16& text);
void SetColor(SkColor color);
void SetTextAlignment(UiTexture::TextAlignment alignment);
void SetMultiLine(bool multiline);
void OnSetSize(gfx::SizeF size) override;
int NumRenderedLinesForTest() const;
UiTexture* GetTextureForTest() const;
private:
UiTexture* GetTexture() const override;
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/vr/elements/text.h"
#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
#include "cc/test/test_skcanvas.h"
#include "chrome/browser/vr/ui_scene.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace vr {
TEST(Text, MultiLine) {
UiScene scene;
testing::NiceMock<cc::MockCanvas> canvas;
const float kInitialSize = 1.0f;
const int kPixelWidth = 512;
// Create an initialize a text element with a long string.
auto text_instance = base::MakeUnique<Text>(kPixelWidth, 0.020);
Text* text = text_instance.get();
text->SetSize(kInitialSize, 0);
text->SetText(base::UTF8ToUTF16(std::string(1000, 'x')));
text->SetInitializedForTesting();
scene.AddUiElement(kRoot, std::move(text_instance));
// Grab a pointer to the underlying texture to inspect it directly.
UiTexture* texture = text->GetTextureForTest();
auto texture_size = texture->GetPreferredTextureSize(kPixelWidth);
// Make sure we get multiple lines of rendered text from the string.
scene.OnBeginFrame(base::TimeTicks(), {0, 0, 0});
texture->DrawAndLayout(&canvas, texture_size);
int initial_num_lines = text->NumRenderedLinesForTest();
EXPECT_GT(initial_num_lines, 1);
// Reduce the field width, and ensure that the number of lines increases.
text->SetSize(kInitialSize / 2, 0);
scene.OnBeginFrame(base::TimeTicks(), {0, 0, 0});
texture->DrawAndLayout(&canvas, texture_size);
EXPECT_GT(text->NumRenderedLinesForTest(), initial_num_lines);
// Enforce single-line rendering.
text->SetMultiLine(false);
scene.OnBeginFrame(base::TimeTicks(), {0, 0, 0});
texture->DrawAndLayout(&canvas, texture_size);
EXPECT_EQ(1, text->NumRenderedLinesForTest());
}
} // namespace vr
......@@ -49,7 +49,7 @@ void TexturedElement::SetRerenderIfNotDirtyForTesting() {
g_rerender_if_not_dirty_for_testing_ = true;
}
bool TexturedElement::UpdateTexture() {
bool TexturedElement::PrepareToDraw() {
if (!initialized_ ||
!(GetTexture()->dirty() || g_rerender_if_not_dirty_for_testing_) ||
!IsVisible())
......@@ -76,10 +76,12 @@ void TexturedElement::UpdateElementSize() {
// the other direction is determined by the associated texture.
gfx::SizeF drawn_size = GetTexture()->GetDrawnSize();
if (resize_vertically_) {
DCHECK_GT(stale_size().width(), 0.f);
float height =
drawn_size.height() / drawn_size.width() * stale_size().width();
SetSize(stale_size().width(), height);
} else {
DCHECK_GT(stale_size().height(), 0.f);
float width =
drawn_size.width() / drawn_size.height() * stale_size().height();
SetSize(width, stale_size().height());
......@@ -102,8 +104,4 @@ void TexturedElement::Render(UiElementRenderer* renderer,
computed_opacity(), size(), corner_radius());
}
bool TexturedElement::PrepareToDraw() {
return UpdateTexture();
}
} // namespace vr
......@@ -57,8 +57,6 @@ class TexturedElement : public UiElement {
bool PrepareToDraw() final;
private:
bool UpdateTexture();
gfx::Size texture_size_;
GLuint texture_handle_ = 0;
int maximum_width_;
......
......@@ -180,8 +180,11 @@ bool UiElement::IsHitTestable() const {
void UiElement::SetSize(float width, float height) {
animation_player_.TransitionSizeTo(last_frame_time_, BOUNDS, size_,
gfx::SizeF(width, height));
OnSetSize(gfx::SizeF(width, height));
}
void UiElement::OnSetSize(gfx::SizeF size) {}
void UiElement::SetVisible(bool visible) {
SetOpacity(visible ? opacity_when_visible_ : 0.0);
}
......
......@@ -207,6 +207,7 @@ class UiElement : public cc::AnimationTarget {
gfx::SizeF size() const;
void SetSize(float width, float hight);
virtual void OnSetSize(gfx::SizeF size);
gfx::PointF local_origin() const { return local_origin_; }
......
......@@ -33,8 +33,9 @@ class TextPerfTest : public testing::Test {
base::MakeUnique<GlTestEnvironment>(kPixelHalfScreen);
provider_ = base::MakeUnique<GaneshSurfaceProvider>();
text_element_ = base::MakeUnique<Text>(kMaximumTextWidthPixels,
kFontHeightMeters, kTextWidthMeters);
text_element_ =
base::MakeUnique<Text>(kMaximumTextWidthPixels, kFontHeightMeters);
text_element_->SetSize(kTextWidthMeters, 0);
text_element_->Initialize(provider_.get());
}
......
......@@ -86,15 +86,16 @@ void OnSuggestionModelAdded(UiScene* scene,
icon->set_draw_phase(kPhaseForeground);
VectorIcon* p_icon = icon.get();
auto content_text = base::MakeUnique<Text>(512, kSuggestionContentTextHeight,
kSuggestionTextFieldWidth);
auto content_text = base::MakeUnique<Text>(512, kSuggestionContentTextHeight);
content_text->set_draw_phase(kPhaseForeground);
content_text->SetVisible(true);
content_text->SetSize(kSuggestionTextFieldWidth, 0);
content_text->SetTextAlignment(UiTexture::kTextAlignmentLeft);
Text* p_content_text = content_text.get();
auto description_text = base::MakeUnique<Text>(
512, kSuggestionDescriptionTextHeight, kSuggestionTextFieldWidth);
auto description_text =
base::MakeUnique<Text>(512, kSuggestionDescriptionTextHeight);
description_text->SetSize(kSuggestionTextFieldWidth, 0);
description_text->set_draw_phase(kPhaseForeground);
description_text->SetVisible(true);
description_text->SetTextAlignment(UiTexture::kTextAlignmentLeft);
......@@ -452,8 +453,7 @@ void UiSceneCreator::CreateSplashScreenForDirectWebVrLaunch() {
std::move(transient_parent));
// Add "Powered by Chrome" text.
auto text = base::MakeUnique<Text>(512, kSplashScreenTextFontHeightM,
kSplashScreenTextWidthM);
auto text = base::MakeUnique<Text>(512, kSplashScreenTextFontHeightM);
BindColor(model_, text.get(), &ColorScheme::splash_screen_text_color,
&Text::SetColor);
text->SetText(l10n_util::GetStringUTF16(IDS_VR_POWERED_BY_CHROME_MESSAGE));
......@@ -533,9 +533,9 @@ void UiSceneCreator::CreateWebVrTimeoutScreen() {
timeout_icon->SetSize(kTimeoutMessageIconWidthDMM,
kTimeoutMessageIconHeightDMM);
auto timeout_text = Create<Text>(
kWebVrTimeoutMessageText, kPhaseOverlayForeground, 512,
kTimeoutMessageTextFontHeightDMM, kTimeoutMessageTextWidthDMM);
auto timeout_text =
Create<Text>(kWebVrTimeoutMessageText, kPhaseOverlayForeground, 512,
kTimeoutMessageTextFontHeightDMM);
timeout_text->SetText(
l10n_util::GetStringUTF16(IDS_VR_WEB_VR_TIMEOUT_MESSAGE));
timeout_text->SetColor(model_->color_scheme().timeout_message_foreground);
......@@ -563,9 +563,9 @@ void UiSceneCreator::CreateWebVrTimeoutScreen() {
BindButtonColors(model_, button.get(), &ColorScheme::button_colors,
&Button::SetButtonColors);
auto timeout_button_text = Create<Text>(
kWebVrTimeoutMessageButtonText, kPhaseOverlayForeground, 512,
kTimeoutMessageTextFontHeightDMM, kTimeoutButtonTextWidthDMM);
auto timeout_button_text =
Create<Text>(kWebVrTimeoutMessageButtonText, kPhaseOverlayForeground, 512,
kTimeoutMessageTextFontHeightDMM);
// Disk-style button text is not uppercase. See crbug.com/787654.
timeout_button_text->SetText(
......@@ -588,8 +588,7 @@ void UiSceneCreator::CreateWebVrTimeoutScreen() {
}
void UiSceneCreator::CreateUnderDevelopmentNotice() {
auto text = base::MakeUnique<Text>(512, kUnderDevelopmentNoticeFontHeightM,
kUnderDevelopmentNoticeWidthM);
auto text = base::MakeUnique<Text>(512, kUnderDevelopmentNoticeFontHeightM);
BindColor(model_, text.get(), &ColorScheme::world_background_text,
&Text::SetColor);
text->SetText(l10n_util::GetStringUTF16(IDS_VR_UNDER_DEVELOPMENT_NOTICE));
......@@ -742,14 +741,14 @@ void UiSceneCreator::CreateVoiceSearchUiGroup() {
},
speech_result_parent)));
auto speech_result =
base::MakeUnique<Text>(256, kVoiceSearchRecognitionResultTextHeight,
kVoiceSearchRecognitionResultTextWidth);
base::MakeUnique<Text>(256, kVoiceSearchRecognitionResultTextHeight);
speech_result->set_name(kSpeechRecognitionResultText);
speech_result->set_draw_phase(kPhaseForeground);
speech_result->SetTranslate(0.f, kSpeechRecognitionResultTextYOffset, 0.f);
speech_result->set_hit_testable(false);
speech_result->SetSize(kVoiceSearchRecognitionResultTextWidth, 0);
speech_result->SetTextAlignment(UiTexture::kTextAlignmentCenter);
speech_result->SetSize(kSuggestionTextFieldWidth, 0);
BindColor(model_, speech_result.get(), &ColorScheme::prompt_foreground,
&Text::SetColor);
speech_result->AddBinding(VR_BIND_FUNC(base::string16, Model, model_,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment