blob: 08bdc0521f1e5e508990c4a21390b0c2978310cd [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 <lib/fzl/vmo-mapper.h>
#include <lib/gfx-font-data/gfx-font-data.h>
#include <text_node.h>
#include <algorithm>
#include "src/lib/syslog/cpp/logger.h"
TextNode::TextNode(scenic::Session* session) : scenic::Node(session) {
session->Enqueue(scenic::NewCreateShapeNodeCmd(id()));
}
TextNode::TextNode(TextNode&& moved) : scenic::Node(std::move(moved)) {}
TextNode::~TextNode() = default;
zx_status_t TextNode::SetText(const std::string s) {
static constexpr const uint32_t kBitmapScale = 1; // Per-dimension pixel scatter ratio.
static constexpr const uint32_t kTextForeground = 0xFF000000; // Opaque black.
static constexpr const uint32_t kTextBackground = 0x7FFFFFFF; // Semi-transparent white.
static constexpr const struct {
uint8_t r = 0xFF;
uint8_t g = 0xFF;
uint8_t b = 0xFF;
uint8_t a = 0xFE;
} kShapeColor; // Nearly opaque white.
const auto& font = gfx_font_9x16;
static constexpr const uint32_t kFontDataBits = 8;
fuchsia::images::ImageInfo image_info;
uint32_t left_pad = font.width - kFontDataBits;
image_info.width = (font.width * s.size() + left_pad) * kBitmapScale;
image_info.height = font.height * kBitmapScale;
image_info.stride = image_info.width * sizeof(uint32_t);
image_info.alpha_format = fuchsia::images::AlphaFormat::NON_PREMULTIPLIED;
size_t image_size = image_info.width * image_info.height * sizeof(uint32_t);
zx::vmo vmo;
fzl::VmoMapper mapper;
zx_status_t status =
mapper.CreateAndMap(image_size, ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, nullptr, &vmo);
if (status != ZX_OK) {
FX_PLOGS(ERROR, status);
return status;
}
auto bitmap_data = reinterpret_cast<uint32_t*>(mapper.start());
size_t x_offset = left_pad * kBitmapScale;
for (uint32_t v = 0; v < image_info.height; ++v) {
for (uint32_t u = 0; u < x_offset; ++u) {
bitmap_data[image_info.width * v + u] = kTextBackground;
}
}
for (auto c : s) {
if (c & 0x80) { // Font only defines lower ASCII bitmaps.
c = '?';
}
const auto* char_data = &font.data[c * font.height];
for (uint32_t v = 0; v < font.height; ++v) {
for (uint32_t u = 0; u < font.width; ++u) {
uint32_t pixel = kTextBackground;
if (u < kFontDataBits && (char_data[v] & (1u << u))) {
pixel = kTextForeground;
}
for (uint32_t vv = 0; vv < kBitmapScale; ++vv) {
for (uint32_t uu = 0; uu < kBitmapScale; ++uu) {
bitmap_data[image_info.width * (v * kBitmapScale + vv) + u * kBitmapScale + uu +
x_offset] = pixel;
}
}
}
}
x_offset += font.width * kBitmapScale;
}
mapper.Unmap();
scenic::Memory memory(session(), std::move(vmo), image_size,
fuchsia::images::MemoryType::HOST_MEMORY);
scenic::Image image(memory, 0, fidl::Clone(image_info));
scenic::Material material(session());
material.SetTexture(image);
// TODO(fxb/38373): support is_alpha
material.SetColor(kShapeColor.r, kShapeColor.g, kShapeColor.b, kShapeColor.a);
scenic::Rectangle shape(session(), image_info.width * 1.0f / kBitmapScale,
image_info.height * 1.0f / kBitmapScale);
session()->Enqueue(scenic::NewSetShapeCmd(id(), shape.id()));
session()->Enqueue(scenic::NewSetMaterialCmd(id(), material.id()));
return ZX_OK;
}