siyao
4 年前
当前提交
720be903
共有 27 个文件被更改,包括 4280 次插入 和 1523 次删除
-
2Samples/UIWidgetsSamples_2019_4/Assets/TextTest.unity
-
395com.unity.uiwidgets/Runtime/ui2/text.cs
-
37engine/Build.bee.cs
-
13engine/README.md
-
6engine/src/TestLoadICU.cpp
-
8engine/src/engine.cc
-
202engine/src/lib/ui/txt/asset_manager_font_provider.cc
-
100engine/src/lib/ui/txt/asset_manager_font_provider.h
-
206engine/src/lib/ui/txt/font_collection.cc
-
33engine/src/lib/ui/txt/font_collection.h
-
157engine/src/lib/ui/txt/icu_util.cc
-
12engine/src/lib/ui/txt/icu_util.h
-
399engine/src/lib/ui/txt/paragraph.cc
-
76engine/src/lib/ui/txt/paragraph.h
-
880engine/src/lib/ui/txt/paragraph_builder.cc
-
88engine/src/lib/ui/txt/paragraph_builder.h
-
1engine/src/render_api.h
-
10engine/src/render_api_d3d11.cc
-
18engine/src/shell/common/shell.cc
-
3engine/src/shell/platform/unity/uiwidgets_panel.cc
-
186Samples/UIWidgetsSamples_2019_4/Assets/TextTest.cs
-
825Samples/UIWidgetsSamples_2019_4/Assets/StreamingAssets/Ranchers-Regular.ttf
-
1001Samples/UIWidgetsSamples_2019_4/Assets/StreamingAssets/Roboto-BlackItalic.ttf
-
1001Samples/UIWidgetsSamples_2019_4/Assets/StreamingAssets/Roboto-Italic.ttf
-
124Samples/UIWidgetsSamples_2019_4/Assets/Behavior1.cs
-
20engine/src/lib/ui/txt/utils.h
|
|||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
#pragma once
|
|||
#include "lib/ui/txt/asset_manager_font_provider.h"
|
|||
#include "asset_manager_font_provider.h"
|
|||
#include "third_party/skia/include/core/SkData.h"
|
|||
#include "third_party/skia/include/core/SkStream.h"
|
|||
#include "third_party/skia/include/core/SkString.h"
|
|||
#include "third_party/skia/include/core/SkTypeface.h"
|
|||
#include "include/core/SkData.h"
|
|||
#include "include/core/SkStream.h"
|
|||
#include "include/core/SkString.h"
|
|||
#include "include/core/SkTypeface.h"
|
|||
namespace { |
|||
namespace { |
|||
void MappingReleaseProc(const void* ptr, void* context) { |
|||
delete reinterpret_cast<fml::Mapping*>(context); |
|||
} |
|||
void MappingReleaseProc(const void* ptr, void* context) { |
|||
delete reinterpret_cast<fml::Mapping*>(context); |
|||
} |
|||
} // anonymous namespace
|
|||
} // anonymous namespace
|
|||
AssetManagerFontProvider::AssetManagerFontProvider( |
|||
std::shared_ptr<AssetManager> asset_manager) |
|||
: asset_manager_(asset_manager) {} |
|||
AssetManagerFontProvider::AssetManagerFontProvider( |
|||
std::shared_ptr<AssetManager> asset_manager) |
|||
: asset_manager_(asset_manager) {} |
|||
AssetManagerFontProvider::~AssetManagerFontProvider() = default; |
|||
AssetManagerFontProvider::~AssetManagerFontProvider() = default; |
|||
// |FontAssetProvider|
|
|||
size_t AssetManagerFontProvider::GetFamilyCount() const { |
|||
return family_names_.size(); |
|||
} |
|||
// |FontAssetProvider|
|
|||
size_t AssetManagerFontProvider::GetFamilyCount() const { |
|||
return family_names_.size(); |
|||
} |
|||
// |FontAssetProvider|
|
|||
std::string AssetManagerFontProvider::GetFamilyName(int index) const { |
|||
FML_DCHECK(index >= 0 && static_cast<size_t>(index) < family_names_.size()); |
|||
return family_names_[index]; |
|||
} |
|||
// |FontAssetProvider|
|
|||
std::string AssetManagerFontProvider::GetFamilyName(int index) const { |
|||
FML_DCHECK(index >= 0 && static_cast<size_t>(index) < family_names_.size()); |
|||
return family_names_[index]; |
|||
} |
|||
// |FontAssetProvider|
|
|||
SkFontStyleSet* AssetManagerFontProvider::MatchFamily( |
|||
const std::string& family_name) { |
|||
auto found = registered_families_.find(CanonicalFamilyName(family_name)); |
|||
if (found == registered_families_.end()) { |
|||
return nullptr; |
|||
} |
|||
sk_sp<SkFontStyleSet> font_style_set = found->second; |
|||
return font_style_set.release(); |
|||
} |
|||
// |FontAssetProvider|
|
|||
SkFontStyleSet* AssetManagerFontProvider::MatchFamily( |
|||
const std::string& family_name) { |
|||
auto found = registered_families_.find(CanonicalFamilyName(family_name)); |
|||
if (found == registered_families_.end()) { |
|||
return nullptr; |
|||
} |
|||
sk_sp<SkFontStyleSet> font_style_set = found->second; |
|||
return font_style_set.release(); |
|||
} |
|||
void AssetManagerFontProvider::RegisterAsset(std::string family_name, |
|||
std::string asset) { |
|||
std::string canonical_name = CanonicalFamilyName(family_name); |
|||
auto family_it = registered_families_.find(canonical_name); |
|||
void AssetManagerFontProvider::RegisterAsset(std::string family_name, |
|||
std::string asset) { |
|||
std::string canonical_name = CanonicalFamilyName(family_name); |
|||
auto family_it = registered_families_.find(canonical_name); |
|||
if (family_it == registered_families_.end()) { |
|||
family_names_.push_back(family_name); |
|||
auto value = std::make_pair( |
|||
canonical_name, |
|||
sk_make_sp<AssetManagerFontStyleSet>(asset_manager_, family_name)); |
|||
family_it = registered_families_.emplace(value).first; |
|||
} |
|||
if (family_it == registered_families_.end()) { |
|||
family_names_.push_back(family_name); |
|||
auto value = std::make_pair( |
|||
canonical_name, |
|||
sk_make_sp<AssetManagerFontStyleSet>(asset_manager_, family_name)); |
|||
family_it = registered_families_.emplace(value).first; |
|||
} |
|||
family_it->second->registerAsset(asset); |
|||
} |
|||
family_it->second->registerAsset(asset); |
|||
} |
|||
AssetManagerFontStyleSet::AssetManagerFontStyleSet( |
|||
std::shared_ptr<AssetManager> asset_manager, |
|||
std::string family_name) |
|||
: asset_manager_(asset_manager), family_name_(family_name) {} |
|||
AssetManagerFontStyleSet::AssetManagerFontStyleSet( |
|||
std::shared_ptr<AssetManager> asset_manager, std::string family_name) |
|||
: asset_manager_(asset_manager), family_name_(family_name) {} |
|||
AssetManagerFontStyleSet::~AssetManagerFontStyleSet() = default; |
|||
AssetManagerFontStyleSet::~AssetManagerFontStyleSet() = default; |
|||
void AssetManagerFontStyleSet::registerAsset(std::string asset) { |
|||
assets_.emplace_back(asset); |
|||
} |
|||
void AssetManagerFontStyleSet::registerAsset(std::string asset) { |
|||
assets_.emplace_back(asset); |
|||
} |
|||
int AssetManagerFontStyleSet::count() { |
|||
return assets_.size(); |
|||
} |
|||
int AssetManagerFontStyleSet::count() { return assets_.size(); } |
|||
void AssetManagerFontStyleSet::getStyle(int index, |
|||
SkFontStyle* style, |
|||
SkString* name) { |
|||
FML_DCHECK(index < static_cast<int>(assets_.size())); |
|||
if (style) { |
|||
sk_sp<SkTypeface> typeface(createTypeface(index)); |
|||
if (typeface) { |
|||
*style = typeface->fontStyle(); |
|||
} |
|||
} |
|||
if (name) { |
|||
*name = family_name_.c_str(); |
|||
} |
|||
void AssetManagerFontStyleSet::getStyle(int index, SkFontStyle* style, |
|||
SkString* name) { |
|||
FML_DCHECK(index < static_cast<int>(assets_.size())); |
|||
if (style) { |
|||
sk_sp<SkTypeface> typeface(createTypeface(index)); |
|||
if (typeface) { |
|||
*style = typeface->fontStyle(); |
|||
} |
|||
if (name) { |
|||
*name = family_name_.c_str(); |
|||
} |
|||
} |
|||
SkTypeface* AssetManagerFontStyleSet::createTypeface(int i) { |
|||
size_t index = i; |
|||
if (index >= assets_.size()) |
|||
return nullptr; |
|||
SkTypeface* AssetManagerFontStyleSet::createTypeface(int i) { |
|||
size_t index = i; |
|||
if (index >= assets_.size()) return nullptr; |
|||
TypefaceAsset& asset = assets_[index]; |
|||
if (!asset.typeface) { |
|||
std::unique_ptr<fml::Mapping> asset_mapping = |
|||
asset_manager_->GetAsMapping(asset.asset); |
|||
if (asset_mapping == nullptr) { |
|||
return nullptr; |
|||
} |
|||
TypefaceAsset& asset = assets_[index]; |
|||
if (!asset.typeface) { |
|||
std::unique_ptr<fml::Mapping> asset_mapping = |
|||
asset_manager_->GetAsMapping(asset.asset); |
|||
if (asset_mapping == nullptr) { |
|||
return nullptr; |
|||
} |
|||
fml::Mapping* asset_mapping_ptr = asset_mapping.release(); |
|||
sk_sp<SkData> asset_data = SkData::MakeWithProc( |
|||
asset_mapping_ptr->GetMapping(), asset_mapping_ptr->GetSize(), |
|||
MappingReleaseProc, asset_mapping_ptr); |
|||
std::unique_ptr<SkMemoryStream> stream = SkMemoryStream::Make(asset_data); |
|||
fml::Mapping* asset_mapping_ptr = asset_mapping.release(); |
|||
sk_sp<SkData> asset_data = SkData::MakeWithProc( |
|||
asset_mapping_ptr->GetMapping(), asset_mapping_ptr->GetSize(), |
|||
MappingReleaseProc, asset_mapping_ptr); |
|||
std::unique_ptr<SkMemoryStream> stream = SkMemoryStream::Make(asset_data); |
|||
// Ownership of the stream is transferred.
|
|||
asset.typeface = SkTypeface::MakeFromStream(std::move(stream)); |
|||
if (!asset.typeface) |
|||
return nullptr; |
|||
} |
|||
// Ownership of the stream is transferred.
|
|||
asset.typeface = SkTypeface::MakeFromStream(std::move(stream)); |
|||
if (!asset.typeface) return nullptr; |
|||
} |
|||
return SkRef(asset.typeface.get()); |
|||
} |
|||
return SkRef(asset.typeface.get()); |
|||
} |
|||
SkTypeface* AssetManagerFontStyleSet::matchStyle(const SkFontStyle& pattern) { |
|||
return matchStyleCSS3(pattern); |
|||
} |
|||
SkTypeface* AssetManagerFontStyleSet::matchStyle(const SkFontStyle& pattern) { |
|||
return matchStyleCSS3(pattern); |
|||
} |
|||
AssetManagerFontStyleSet::TypefaceAsset::TypefaceAsset(std::string a) |
|||
: asset(std::move(a)) {} |
|||
AssetManagerFontStyleSet::TypefaceAsset::TypefaceAsset(std::string a) |
|||
: asset(std::move(a)) {} |
|||
AssetManagerFontStyleSet::TypefaceAsset::TypefaceAsset( |
|||
const AssetManagerFontStyleSet::TypefaceAsset& other) = default; |
|||
AssetManagerFontStyleSet::TypefaceAsset::TypefaceAsset( |
|||
const AssetManagerFontStyleSet::TypefaceAsset& other) = default; |
|||
AssetManagerFontStyleSet::TypefaceAsset::~TypefaceAsset() = default; |
|||
AssetManagerFontStyleSet::TypefaceAsset::~TypefaceAsset() = default; |
|||
} // namespace flutter
|
|||
} // namespace uiwidgets
|
|
|||
#include "lib/ui/txt/font_collection.h"
|
|||
#pragma once
|
|||
|
|||
#include "font_collection.h"
|
|||
#include "include/core/SkFontMgr.h"
|
|||
#include "include/core/SkGraphics.h"
|
|||
#include "include/core/SkStream.h"
|
|||
#include "include/core/SkTypeface.h"
|
|||
#include "lib/ui/ui_mono_state.h"
|
|||
#include "third_party/skia/include/core/SkFontMgr.h"
|
|||
#include "third_party/skia/include/core/SkGraphics.h"
|
|||
#include "third_party/skia/include/core/SkStream.h"
|
|||
#include "third_party/skia/include/core/SkTypeface.h"
|
|||
namespace { |
|||
typedef void (*LoadFontCallback)(Mono_Handle callback_handle); |
|||
namespace { |
|||
UIWIDGETS_API(void) |
|||
LoadFontFromList(uint8_t* font_data, int size, |
|||
LoadFontCallback loadFontCallback, Mono_Handle callbackHandle, |
|||
char* family_name) { |
|||
FontCollection& font_collection = |
|||
UIMonoState::Current()->window()->client()->GetFontCollection(); |
|||
font_collection.LoadFontFromList(font_data, size, family_name); |
|||
loadFontCallback(callbackHandle); |
|||
} |
|||
/* void LoadFontFromList(tonic::Uint8List& font_data,
|
|||
Dart_Handle callback, |
|||
std::string family_name) { |
|||
FontCollection& font_collection = |
|||
UIDartState::Current()->window()->client()->GetFontCollection(); |
|||
font_collection.LoadFontFromList(font_data.data(), font_data.num_elements(), |
|||
family_name); |
|||
font_data.Release(); |
|||
tonic::DartInvoke(callback, { tonic::ToDart(0) }); |
|||
}*/ |
|||
} // namespace
|
|||
//void _LoadFontFromList(Dart_NativeArguments args) {
|
|||
// UIDartState::ThrowIfUIOperationsProhibited();
|
|||
// tonic::DartCallStatic(LoadFontFromList, args);
|
|||
//}
|
|||
FontCollection::FontCollection() |
|||
: collection_(std::make_shared<txt::FontCollection>()) { |
|||
dynamic_font_manager_ = sk_make_sp<txt::DynamicFontManager>(); |
|||
collection_->SetDynamicFontManager(dynamic_font_manager_); |
|||
} |
|||
} // namespace
|
|||
FontCollection::~FontCollection() { |
|||
collection_.reset(); |
|||
SkGraphics::PurgeFontCache(); |
|||
} |
|||
FontCollection::FontCollection() |
|||
: collection_(std::make_shared<txt::FontCollection>()) { |
|||
dynamic_font_manager_ = sk_make_sp<txt::DynamicFontManager>(); |
|||
collection_->SetDynamicFontManager(dynamic_font_manager_); |
|||
} |
|||
std::shared_ptr<txt::FontCollection> FontCollection::GetFontCollection() const { |
|||
return collection_; |
|||
} |
|||
FontCollection::~FontCollection() { |
|||
collection_.reset(); |
|||
SkGraphics::PurgeFontCache(); |
|||
} |
|||
void FontCollection::SetupDefaultFontManager() { |
|||
collection_->SetupDefaultFontManager(); |
|||
} |
|||
void FontCollection::RegisterFonts( |
|||
std::shared_ptr<AssetManager> asset_manager) { |
|||
std::unique_ptr<fml::Mapping> manifest_mapping = |
|||
asset_manager->GetAsMapping("FontManifest.json"); |
|||
if (manifest_mapping == nullptr) { |
|||
FML_DLOG(WARNING) << "Could not find the font manifest in the asset store."; |
|||
return; |
|||
} |
|||
std::shared_ptr<txt::FontCollection> FontCollection::GetFontCollection() const { |
|||
return collection_; |
|||
} |
|||
|
|||
void FontCollection::SetupDefaultFontManager() { |
|||
collection_->SetupDefaultFontManager(); |
|||
} |
|||
|
|||
void FontCollection::RegisterFonts( |
|||
std::shared_ptr<AssetManager> asset_manager) { |
|||
std::unique_ptr<fml::Mapping> manifest_mapping = |
|||
asset_manager->GetAsMapping("FontManifest.json"); |
|||
if (manifest_mapping == nullptr) { |
|||
FML_DLOG(WARNING) << "Could not find the font manifest in the asset store."; |
|||
return; |
|||
} |
|||
|
|||
rapidjson::Document document; |
|||
static_assert(sizeof(decltype(document)::Ch) == sizeof(uint8_t), ""); |
|||
document.Parse(reinterpret_cast<const decltype(document)::Ch*>( |
|||
manifest_mapping->GetMapping()), |
|||
manifest_mapping->GetSize()); |
|||
|
|||
if (document.HasParseError()) { |
|||
FML_DLOG(WARNING) << "Error parsing the font manifest in the asset store."; |
|||
return; |
|||
} |
|||
rapidjson::Document document; |
|||
static_assert(sizeof(decltype(document)::Ch) == sizeof(uint8_t), ""); |
|||
document.Parse(reinterpret_cast<const decltype(document)::Ch*>( |
|||
manifest_mapping->GetMapping()), |
|||
manifest_mapping->GetSize()); |
|||
// Structure described in https://flutter.io/custom-fonts/
|
|||
if (document.HasParseError()) { |
|||
FML_DLOG(WARNING) << "Error parsing the font manifest in the asset store."; |
|||
return; |
|||
} |
|||
if (!document.IsArray()) { |
|||
return; |
|||
} |
|||
// Structure described in https://flutter.io/custom-fonts/
|
|||
auto font_provider = |
|||
std::make_unique<AssetManagerFontProvider>(asset_manager); |
|||
if (!document.IsArray()) { |
|||
return; |
|||
} |
|||
for (const auto& family : document.GetArray()) { |
|||
auto family_name = family.FindMember("family"); |
|||
if (family_name == family.MemberEnd() || !family_name->value.IsString()) { |
|||
continue; |
|||
} |
|||
auto font_provider = |
|||
std::make_unique<AssetManagerFontProvider>(asset_manager); |
|||
auto family_fonts = family.FindMember("fonts"); |
|||
if (family_fonts == family.MemberEnd() || !family_fonts->value.IsArray()) { |
|||
continue; |
|||
} |
|||
for (const auto& family : document.GetArray()) { |
|||
auto family_name = family.FindMember("family"); |
|||
if (family_name == family.MemberEnd() || !family_name->value.IsString()) { |
|||
continue; |
|||
} |
|||
for (const auto& family_font : family_fonts->value.GetArray()) { |
|||
if (!family_font.IsObject()) { |
|||
continue; |
|||
} |
|||
auto family_fonts = family.FindMember("fonts"); |
|||
if (family_fonts == family.MemberEnd() || !family_fonts->value.IsArray()) { |
|||
continue; |
|||
} |
|||
auto font_asset = family_font.FindMember("asset"); |
|||
if (font_asset == family_font.MemberEnd() || |
|||
!font_asset->value.IsString()) { |
|||
continue; |
|||
} |
|||
for (const auto& family_font : family_fonts->value.GetArray()) { |
|||
if (!family_font.IsObject()) { |
|||
continue; |
|||
} |
|||
// TODO: Handle weights and styles.
|
|||
font_provider->RegisterAsset(family_name->value.GetString(), |
|||
font_asset->value.GetString()); |
|||
} |
|||
} |
|||
auto font_asset = family_font.FindMember("asset"); |
|||
if (font_asset == family_font.MemberEnd() || |
|||
!font_asset->value.IsString()) { |
|||
continue; |
|||
} |
|||
collection_->SetAssetFontManager( |
|||
sk_make_sp<txt::AssetFontManager>(std::move(font_provider))); |
|||
// TODO: Handle weights and styles.
|
|||
font_provider->RegisterAsset(family_name->value.GetString(), |
|||
font_asset->value.GetString()); |
|||
} |
|||
void FontCollection::LoadFontFromList(const uint8_t* font_data, |
|||
int length, |
|||
std::string family_name) { |
|||
std::unique_ptr<SkStreamAsset> font_stream = |
|||
std::make_unique<SkMemoryStream>(font_data, length, true); |
|||
sk_sp<SkTypeface> typeface = |
|||
SkTypeface::MakeFromStream(std::move(font_stream)); |
|||
txt::TypefaceFontAssetProvider& font_provider = |
|||
dynamic_font_manager_->font_provider(); |
|||
if (family_name.empty()) { |
|||
font_provider.RegisterTypeface(typeface); |
|||
} |
|||
else { |
|||
font_provider.RegisterTypeface(typeface, family_name); |
|||
} |
|||
collection_->ClearFontFamilyCache(); |
|||
} |
|||
collection_->SetAssetFontManager( |
|||
sk_make_sp<txt::AssetFontManager>(std::move(font_provider))); |
|||
} |
|||
|
|||
void FontCollection::LoadFontFromList(const uint8_t* font_data, int length, |
|||
std::string family_name) { |
|||
std::unique_ptr<SkStreamAsset> font_stream = |
|||
std::make_unique<SkMemoryStream>(font_data, length, true); |
|||
sk_sp<SkTypeface> typeface = |
|||
SkTypeface::MakeFromStream(std::move(font_stream)); |
|||
txt::TypefaceFontAssetProvider& font_provider = |
|||
dynamic_font_manager_->font_provider(); |
|||
if (family_name.empty()) { |
|||
font_provider.RegisterTypeface(typeface); |
|||
} else { |
|||
font_provider.RegisterTypeface(typeface, family_name); |
|||
} |
|||
collection_->ClearFontFamilyCache(); |
|||
} |
|||
} // namespace flutter
|
|||
} // namespace uiwidgets
|
|
|||
#include "lib/ui/ui_mono_state.h"
|
|||
#include "utils.h"
|
|||
#include <flutter\third_party\txt\src\txt\paragraph.h>
|
|||
#include "flutter/third_party/txt/src/txt/paragraph.h"
|
|||
#include "lib/ui/ui_mono_state.h"
|
|||
Paragraph::Paragraph(std::unique_ptr<txt::Paragraph> paragraph) |
|||
: m_paragraph(std::move(paragraph)) {} |
|||
Paragraph::Paragraph(std::unique_ptr<txt::Paragraph> paragraph) |
|||
: m_paragraph(std::move(paragraph)) {} |
|||
Paragraph::~Paragraph() = default; |
|||
Paragraph::~Paragraph() = default; |
|||
size_t Paragraph::GetAllocationSize() { |
|||
// We don't have an accurate accounting of the paragraph's memory consumption,
|
|||
// so return a fixed size to indicate that its impact is more than the size
|
|||
// of the Paragraph class.
|
|||
return 2000; |
|||
} |
|||
size_t Paragraph::GetAllocationSize() { |
|||
// We don't have an accurate accounting of the paragraph's memory consumption,
|
|||
// so return a fixed size to indicate that its impact is more than the size
|
|||
// of the Paragraph class.
|
|||
return 2000; |
|||
} |
|||
double Paragraph::width() { |
|||
return m_paragraph->GetMaxWidth(); |
|||
} |
|||
float Paragraph::width() { return m_paragraph->GetMaxWidth(); } |
|||
double Paragraph::height() { |
|||
return m_paragraph->GetHeight(); |
|||
} |
|||
float Paragraph::height() { return m_paragraph->GetHeight(); } |
|||
double Paragraph::longestLine() { |
|||
return m_paragraph->GetLongestLine(); |
|||
} |
|||
float Paragraph::longestLine() { return m_paragraph->GetLongestLine(); } |
|||
double Paragraph::minIntrinsicWidth() { |
|||
return m_paragraph->GetMinIntrinsicWidth(); |
|||
} |
|||
float Paragraph::minIntrinsicWidth() { |
|||
return m_paragraph->GetMinIntrinsicWidth(); |
|||
} |
|||
double Paragraph::maxIntrinsicWidth() { |
|||
return m_paragraph->GetMaxIntrinsicWidth(); |
|||
} |
|||
float Paragraph::maxIntrinsicWidth() { |
|||
return m_paragraph->GetMaxIntrinsicWidth(); |
|||
} |
|||
double Paragraph::alphabeticBaseline() { |
|||
return m_paragraph->GetAlphabeticBaseline(); |
|||
} |
|||
float Paragraph::alphabeticBaseline() { |
|||
return m_paragraph->GetAlphabeticBaseline(); |
|||
} |
|||
double Paragraph::ideographicBaseline() { |
|||
return m_paragraph->GetIdeographicBaseline(); |
|||
} |
|||
float Paragraph::ideographicBaseline() { |
|||
return m_paragraph->GetIdeographicBaseline(); |
|||
} |
|||
bool Paragraph::didExceedMaxLines() { |
|||
return m_paragraph->DidExceedMaxLines(); |
|||
} |
|||
bool Paragraph::didExceedMaxLines() { return m_paragraph->DidExceedMaxLines(); } |
|||
void Paragraph::layout(double width) { |
|||
m_paragraph->Layout(width); |
|||
} |
|||
void Paragraph::layout(float width) { m_paragraph->Layout(width); } |
|||
void Paragraph::paint(Canvas * canvas, double x, double y) { |
|||
SkCanvas* sk_canvas = canvas->canvas(); |
|||
if (!sk_canvas) |
|||
return; |
|||
m_paragraph->Paint(sk_canvas, x, y); |
|||
} |
|||
void Paragraph::paint(Canvas* canvas, float x, float y) { |
|||
SkCanvas* sk_canvas = canvas->canvas(); |
|||
if (!sk_canvas) return; |
|||
m_paragraph->Paint(sk_canvas, x, y); |
|||
} |
|||
static Float32List EncodeTextBoxes( |
|||
const std::vector<txt::Paragraph::TextBox> & boxes) { |
|||
// Layout:
|
|||
// First value is the number of values.
|
|||
// Then there are boxes.size() groups of 5 which are LTRBD, where D is the
|
|||
// text direction index.
|
|||
Float32List result = { |
|||
new float[boxes.size() * 5], |
|||
boxes.size() * 5 |
|||
}; |
|||
static void EncodeTextBoxes(const std::vector<txt::Paragraph::TextBox>& boxes, |
|||
float* result) { |
|||
// Layout:
|
|||
// First value is the number of values.
|
|||
// Then there are boxes.size() groups of 5 which are LTRBD, where D is the
|
|||
// text direction index.
|
|||
unsigned long position = 0; |
|||
for (unsigned long i = 0; i < boxes.size(); i++) { |
|||
const txt::Paragraph::TextBox& box = boxes[i]; |
|||
result.data[position++] = box.rect.fLeft; |
|||
result.data[position++] = box.rect.fTop; |
|||
result.data[position++] = box.rect.fRight; |
|||
result.data[position++] = box.rect.fBottom; |
|||
result.data[position++] = static_cast<float>(box.direction); |
|||
} |
|||
return result; |
|||
} |
|||
unsigned long position = 0; |
|||
for (unsigned long i = 0; i < boxes.size(); i++) { |
|||
const txt::Paragraph::TextBox& box = boxes[i]; |
|||
result[position++] = box.rect.fLeft; |
|||
result[position++] = box.rect.fTop; |
|||
result[position++] = box.rect.fRight; |
|||
result[position++] = box.rect.fBottom; |
|||
result[position++] = static_cast<float>(box.direction); |
|||
} |
|||
} |
|||
Float32List Paragraph::getRectsForRange(unsigned start, |
|||
unsigned end, |
|||
unsigned boxHeightStyle, |
|||
unsigned boxWidthStyle) { |
|||
std::vector<txt::Paragraph::TextBox> boxes = m_paragraph->GetRectsForRange( |
|||
start, end, static_cast<txt::Paragraph::RectHeightStyle>(boxHeightStyle), |
|||
static_cast<txt::Paragraph::RectWidthStyle>(boxWidthStyle)); |
|||
return EncodeTextBoxes(boxes); |
|||
} |
|||
int Paragraph::getRectsForRangeSize(unsigned start, unsigned end, |
|||
unsigned boxHeightStyle, |
|||
unsigned boxWidthStyle) { |
|||
std::vector<txt::Paragraph::TextBox> boxes = m_paragraph->GetRectsForRange( |
|||
start, end, static_cast<txt::Paragraph::RectHeightStyle>(boxHeightStyle), |
|||
static_cast<txt::Paragraph::RectWidthStyle>(boxWidthStyle)); |
|||
return boxes.size() * 5; |
|||
} |
|||
Float32List Paragraph::getRectsForPlaceholders() { |
|||
std::vector<txt::Paragraph::TextBox> boxes = |
|||
m_paragraph->GetRectsForPlaceholders(); |
|||
return EncodeTextBoxes(boxes); |
|||
void Paragraph::getRectsForRange(float* data, unsigned start, unsigned end, |
|||
unsigned boxHeightStyle, |
|||
unsigned boxWidthStyle) { |
|||
std::vector<txt::Paragraph::TextBox> boxes = m_paragraph->GetRectsForRange( |
|||
start, end, static_cast<txt::Paragraph::RectHeightStyle>(boxHeightStyle), |
|||
static_cast<txt::Paragraph::RectWidthStyle>(boxWidthStyle)); |
|||
EncodeTextBoxes(boxes, data); |
|||
} |
|||
|
|||
int Paragraph::getRectsForPlaceholdersSize() { |
|||
std::vector<txt::Paragraph::TextBox> boxes = |
|||
m_paragraph->GetRectsForPlaceholders(); |
|||
return boxes.size() * 5; |
|||
} |
|||
|
|||
void Paragraph::getRectsForPlaceholders(float* data) { |
|||
std::vector<txt::Paragraph::TextBox> boxes = |
|||
m_paragraph->GetRectsForPlaceholders(); |
|||
return EncodeTextBoxes(boxes, data); |
|||
} |
|||
|
|||
void Paragraph::getPositionForOffset(float dx, float dy, int* offset) { |
|||
txt::Paragraph::PositionWithAffinity pos = |
|||
m_paragraph->GetGlyphPositionAtCoordinate(dx, dy); |
|||
offset[0] = pos.position; |
|||
offset[1] = static_cast<int>(pos.affinity); |
|||
} |
|||
|
|||
void Paragraph::getWordBoundary(unsigned offset, int* boundaryPtr) { |
|||
txt::Paragraph::Range<size_t> point = m_paragraph->GetWordBoundary(offset); |
|||
boundaryPtr[0] = point.start; |
|||
boundaryPtr[1] = point.end; |
|||
} |
|||
|
|||
void Paragraph::getLineBoundary(unsigned offset, int* boundaryPtr) { |
|||
std::vector<txt::LineMetrics> metrics = m_paragraph->GetLineMetrics(); |
|||
int line_start = -1; |
|||
int line_end = -1; |
|||
for (txt::LineMetrics& line : metrics) { |
|||
if (offset >= line.start_index && offset <= line.end_index) { |
|||
line_start = line.start_index; |
|||
line_end = line.end_index; |
|||
break; |
|||
} |
|||
boundaryPtr[0] = line_start; |
|||
boundaryPtr[1] = line_end; |
|||
} |
|||
SizeTList Paragraph::getPositionForOffset(double dx, double dy) { |
|||
SizeTList result = { |
|||
new size_t[2], |
|||
2 |
|||
}; |
|||
txt::Paragraph::PositionWithAffinity pos = |
|||
m_paragraph->GetGlyphPositionAtCoordinate(dx, dy); |
|||
result.data[0] = pos.position; |
|||
result.data[1] = static_cast<int>(pos.affinity); |
|||
return result; |
|||
} |
|||
int Paragraph::computeLineMetricsSize() { |
|||
std::vector<txt::LineMetrics> metrics = m_paragraph->GetLineMetrics(); |
|||
|
|||
// Layout:
|
|||
// boxes.size() groups of 9 which are the line metrics
|
|||
// properties
|
|||
return metrics.size() * 9; |
|||
} |
|||
|
|||
void Paragraph::computeLineMetrics(float* result) { |
|||
std::vector<txt::LineMetrics> metrics = m_paragraph->GetLineMetrics(); |
|||
SizeTList Paragraph::getWordBoundary(unsigned offset) { |
|||
txt::Paragraph::Range<size_t> point = m_paragraph->GetWordBoundary(offset); |
|||
SizeTList result = { |
|||
new size_t[2], |
|||
2 |
|||
}; |
|||
result.data[0] = point.start; |
|||
result.data[1] = point.end; |
|||
return result; |
|||
} |
|||
// Layout:
|
|||
// boxes.size() groups of 9 which are the line metrics
|
|||
// properties
|
|||
unsigned long position = 0; |
|||
for (unsigned long i = 0; i < metrics.size(); i++) { |
|||
const txt::LineMetrics& line = metrics[i]; |
|||
result[position++] = static_cast<float>(line.hard_break); |
|||
result[position++] = line.ascent; |
|||
result[position++] = line.descent; |
|||
result[position++] = line.unscaled_ascent; |
|||
// We add then round to get the height. The
|
|||
// definition of height here is different
|
|||
// than the one in LibTxt.
|
|||
result[position++] = round(line.ascent + line.descent); |
|||
result[position++] = line.width; |
|||
result[position++] = line.left; |
|||
result[position++] = line.baseline; |
|||
result[position++] = static_cast<float>(line.line_number); |
|||
} |
|||
} |
|||
SizeTList Paragraph::getLineBoundary(unsigned offset) { |
|||
std::vector<txt::LineMetrics> metrics = m_paragraph->GetLineMetrics(); |
|||
int line_start = -1; |
|||
int line_end = -1; |
|||
for (txt::LineMetrics& line : metrics) { |
|||
if (offset >= line.start_index && offset <= line.end_index) { |
|||
line_start = line.start_index; |
|||
line_end = line.end_index; |
|||
break; |
|||
} |
|||
} |
|||
SizeTList result = { |
|||
new size_t[2], |
|||
2 |
|||
}; |
|||
result.data[0] = line_start; |
|||
result.data[1] = line_end; |
|||
return result; |
|||
} |
|||
UIWIDGETS_API(float) Paragraph_width(Paragraph* ptr) { return ptr->width(); } |
|||
Float32List Paragraph::computeLineMetrics() { |
|||
std::vector<txt::LineMetrics> metrics = m_paragraph->GetLineMetrics(); |
|||
UIWIDGETS_API(float) Paragraph_height(Paragraph* ptr) { return ptr->height(); } |
|||
// Layout:
|
|||
// boxes.size() groups of 9 which are the line metrics
|
|||
// properties
|
|||
Float32List result = { |
|||
new float[metrics.size() * 9], |
|||
2 |
|||
}; |
|||
unsigned long position = 0; |
|||
for (unsigned long i = 0; i < metrics.size(); i++) { |
|||
const txt::LineMetrics& line = metrics[i]; |
|||
result.data[position++] = static_cast<double>(line.hard_break); |
|||
result.data[position++] = line.ascent; |
|||
result.data[position++] = line.descent; |
|||
result.data[position++] = line.unscaled_ascent; |
|||
// We add then round to get the height. The
|
|||
// definition of height here is different
|
|||
// than the one in LibTxt.
|
|||
result.data[position++] = round(line.ascent + line.descent); |
|||
result.data[position++] = line.width; |
|||
result.data[position++] = line.left; |
|||
result.data[position++] = line.baseline; |
|||
result.data[position++] = static_cast<double>(line.line_number); |
|||
} |
|||
UIWIDGETS_API(float) Paragraph_longestLine(Paragraph* ptr) { |
|||
return ptr->longestLine(); |
|||
} |
|||
return result; |
|||
} |
|||
UIWIDGETS_API(float) Paragraph_minIntrinsicWidth(Paragraph* ptr) { |
|||
return ptr->minIntrinsicWidth(); |
|||
} |
|||
UIWIDGETS_API(double) Paragraph_width(Paragraph* ptr) { |
|||
return ptr->width(); |
|||
} |
|||
UIWIDGETS_API(float) Paragraph_maxIntrinsicWidth(Paragraph* ptr) { |
|||
return ptr->maxIntrinsicWidth(); |
|||
} |
|||
UIWIDGETS_API(double) Paragraph_height(Paragraph* ptr) { |
|||
return ptr->height(); |
|||
} |
|||
UIWIDGETS_API(float) Paragraph_alphabeticBaseline(Paragraph* ptr) { |
|||
return ptr->alphabeticBaseline(); |
|||
} |
|||
UIWIDGETS_API(double) Paragraph_longestLine(Paragraph* ptr) { |
|||
return ptr->longestLine(); |
|||
} |
|||
UIWIDGETS_API(float) Paragraph_ideographicBaseline(Paragraph* ptr) { |
|||
return ptr->ideographicBaseline(); |
|||
} |
|||
UIWIDGETS_API(double) Paragraph_minIntrinsicWidth(Paragraph* ptr) { |
|||
return ptr->minIntrinsicWidth(); |
|||
} |
|||
UIWIDGETS_API(bool) Paragraph_didExceedMaxLines(Paragraph* ptr) { |
|||
return ptr->didExceedMaxLines(); |
|||
} |
|||
UIWIDGETS_API(double) Paragraph_maxIntrinsicWidth(Paragraph* ptr) { |
|||
return ptr->maxIntrinsicWidth(); |
|||
} |
|||
UIWIDGETS_API(void) Paragraph_layout(Paragraph* ptr, float width) { |
|||
ptr->layout(width); |
|||
} |
|||
UIWIDGETS_API(double) Paragraph_alphabeticBaseline(Paragraph* ptr) { |
|||
return ptr->alphabeticBaseline(); |
|||
} |
|||
UIWIDGETS_API(int) |
|||
Paragraph_getRectsForRangeSize(Paragraph* ptr, int start, int end, |
|||
int boxHeightStyle, int boxWidthStyle) { |
|||
return ptr->getRectsForRangeSize(start, end, boxHeightStyle, boxWidthStyle); |
|||
} |
|||
UIWIDGETS_API(double) Paragraph_ideographicBaseline(Paragraph* ptr) { |
|||
return ptr->ideographicBaseline(); |
|||
} |
|||
UIWIDGETS_API(void) |
|||
Paragraph_getRectsForRange(Paragraph* ptr, float* data, int start, int end, |
|||
int boxHeightStyle, int boxWidthStyle) { |
|||
ptr->getRectsForRange(data, start, end, boxHeightStyle, boxWidthStyle); |
|||
} |
|||
UIWIDGETS_API(bool) Paragraph_didExceedMaxLines(Paragraph* ptr) { |
|||
return ptr->didExceedMaxLines(); |
|||
} |
|||
UIWIDGETS_API(int) |
|||
Paragraph_getRectsForPlaceholdersSize(Paragraph* ptr) { |
|||
return ptr->getRectsForPlaceholdersSize(); |
|||
} |
|||
UIWIDGETS_API(void) Paragraph_layout(Paragraph* ptr, double width) { |
|||
ptr->layout(width); |
|||
} |
|||
UIWIDGETS_API(void) |
|||
Paragraph_getRectsForPlaceholders(Paragraph* ptr, float* data) { |
|||
ptr->getRectsForPlaceholders(data); |
|||
} |
|||
UIWIDGETS_API(Float32List) Paragraph_getRectsForRange(Paragraph* ptr, int start, int end, int boxHeightStyle, int boxWidthStyle) { |
|||
return ptr->getRectsForRange(start, end, boxHeightStyle, boxWidthStyle); |
|||
} |
|||
UIWIDGETS_API(void) |
|||
Paragraph_getPositionForOffset(Paragraph* ptr, float dx, float dy, |
|||
int* offset) { |
|||
return ptr->getPositionForOffset(dx, dy, offset); |
|||
} |
|||
UIWIDGETS_API(Float32List) Paragraph_getRectsForPlaceholders(Paragraph* ptr) { |
|||
return ptr->getRectsForPlaceholders(); |
|||
} |
|||
UIWIDGETS_API(SizeTList) Paragraph_getPositionForOffset(Paragraph* ptr, double dx, double dy) { |
|||
return ptr->getPositionForOffset(dx, dy); |
|||
} |
|||
UIWIDGETS_API(void) |
|||
Paragraph_getWordBoundary(Paragraph* ptr, int offset, int* boundaryPtr) { |
|||
ptr->getWordBoundary(offset, boundaryPtr); |
|||
} |
|||
UIWIDGETS_API(SizeTList) Paragraph_getWordBoundary(Paragraph* ptr, int offset) { |
|||
return ptr->getWordBoundary(offset); |
|||
} |
|||
UIWIDGETS_API(void) |
|||
Paragraph_getLineBoundary(Paragraph* ptr, int offset, int* boundaryPtr) { |
|||
ptr->getLineBoundary(offset, boundaryPtr); |
|||
} |
|||
UIWIDGETS_API(SizeTList) Paragraph_getLineBoundary(Paragraph* ptr, int offset) { |
|||
return ptr->getLineBoundary(offset); |
|||
} |
|||
UIWIDGETS_API(void) |
|||
Paragraph_paint(Paragraph* ptr, Canvas* canvas, float x, float y) { |
|||
ptr->paint(canvas, x, y); |
|||
} |
|||
UIWIDGETS_API(void) Paragraph_paint(Paragraph* ptr, Canvas* canvas, double x, double y) { |
|||
ptr->paint(canvas, x, y); |
|||
} |
|||
UIWIDGETS_API(int) Paragraph_computeLineMetricsSize(Paragraph* ptr) { |
|||
return ptr->computeLineMetricsSize(); |
|||
} |
|||
UIWIDGETS_API(Float32List) Paragraph_computeLineMetrics(Paragraph* ptr) { |
|||
return ptr->computeLineMetrics(); |
|||
} |
|||
UIWIDGETS_API(void) Paragraph_computeLineMetrics(Paragraph* ptr, float* data) { |
|||
ptr->computeLineMetrics(data); |
|||
} |
|||
UIWIDGETS_API(void) Paragraph_dispose(Paragraph* ptr) { |
|||
ptr->Release(); |
|||
} |
|||
} |
|||
UIWIDGETS_API(void) Paragraph_dispose(Paragraph* ptr) { ptr->Release(); } |
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include <flutter/fml/memory/ref_counted.h> |
|||
#include <src\lib\ui\painting\canvas.h> |
|||
#include <flutter\third_party\txt\src\txt\paragraph.h> |
|||
#include "utils.h" |
|||
#include "flutter/fml/memory/ref_counted.h" |
|||
#include "flutter/third_party/txt/src/txt/paragraph.h" |
|||
#include "src/lib/ui/painting/canvas.h" |
|||
class Paragraph : public fml::RefCountedThreadSafe<Paragraph> { |
|||
FML_FRIEND_MAKE_REF_COUNTED(Paragraph); |
|||
class Paragraph : public fml::RefCountedThreadSafe<Paragraph> { |
|||
FML_FRIEND_MAKE_REF_COUNTED(Paragraph); |
|||
public: |
|||
static fml::RefPtr<Paragraph> Create(); |
|||
|
|||
static fml::RefPtr<Paragraph> Create(std::unique_ptr<txt::Paragraph> txt_paragraph) { |
|||
return fml::MakeRefCounted<Paragraph>(std::move(txt_paragraph)); |
|||
} |
|||
public: |
|||
static fml::RefPtr<Paragraph> Create(); |
|||
~Paragraph(); |
|||
static fml::RefPtr<Paragraph> Create( |
|||
std::unique_ptr<txt::Paragraph> txt_paragraph) { |
|||
return fml::MakeRefCounted<Paragraph>(std::move(txt_paragraph)); |
|||
} |
|||
~Paragraph(); |
|||
double width(); |
|||
double height(); |
|||
double longestLine(); |
|||
double minIntrinsicWidth(); |
|||
double maxIntrinsicWidth(); |
|||
double alphabeticBaseline(); |
|||
double ideographicBaseline(); |
|||
bool didExceedMaxLines(); |
|||
float width(); |
|||
float height(); |
|||
float longestLine(); |
|||
float minIntrinsicWidth(); |
|||
float maxIntrinsicWidth(); |
|||
float alphabeticBaseline(); |
|||
float ideographicBaseline(); |
|||
bool didExceedMaxLines(); |
|||
void layout(double width); |
|||
void paint(Canvas* canvas, double x, double y); |
|||
void layout(float width); |
|||
void paint(Canvas* canvas, float x, float y); |
|||
Float32List getRectsForRange(unsigned start, |
|||
unsigned end, |
|||
unsigned boxHeightStyle, |
|||
unsigned boxWidthStyle); |
|||
Float32List getRectsForPlaceholders(); |
|||
SizeTList getPositionForOffset(double dx, double dy); |
|||
SizeTList getWordBoundary(unsigned offset); |
|||
SizeTList getLineBoundary(unsigned offset); |
|||
Float32List computeLineMetrics(); |
|||
int getRectsForRangeSize(unsigned start, unsigned end, |
|||
unsigned boxHeightStyle, unsigned boxWidthStyle); |
|||
void getRectsForRange(float* data, unsigned start, unsigned end, |
|||
unsigned boxHeightStyle, unsigned boxWidthStyle); |
|||
int getRectsForPlaceholdersSize(); |
|||
void getRectsForPlaceholders(float* data); |
|||
void getPositionForOffset(float dx, float dy, int* offset); |
|||
void getWordBoundary(unsigned offset, int* boundaryPtr); |
|||
void getLineBoundary(unsigned offset, int* boundaryPtr); |
|||
int computeLineMetricsSize(); |
|||
void computeLineMetrics(float* data); |
|||
size_t GetAllocationSize(); |
|||
std::unique_ptr<txt::Paragraph> m_paragraph; |
|||
private: |
|||
|
|||
size_t GetAllocationSize(); |
|||
std::unique_ptr<txt::Paragraph> m_paragraph; |
|||
explicit Paragraph(std::unique_ptr<txt::Paragraph> paragraph); |
|||
}; |
|||
private: |
|||
explicit Paragraph(std::unique_ptr<txt::Paragraph> paragraph); |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "lib/ui/ui_mono_state.h"
|
|||
|
|||
#include "lib/ui/ui_mono_state.h"
|
|||
#include "TestLoadICU.h"
|
|||
namespace { |
|||
|
|||
// TextStyle
|
|||
|
|||
const int tsColorIndex = 1; |
|||
const int tsTextDecorationIndex = 2; |
|||
const int tsTextDecorationColorIndex = 3; |
|||
const int tsTextDecorationStyleIndex = 4; |
|||
const int tsFontWeightIndex = 5; |
|||
const int tsFontStyleIndex = 6; |
|||
const int tsTextBaselineIndex = 7; |
|||
const int tsTextDecorationThicknessIndex = 8; |
|||
const int tsFontFamilyIndex = 9; |
|||
const int tsFontSizeIndex = 10; |
|||
const int tsLetterSpacingIndex = 11; |
|||
const int tsWordSpacingIndex = 12; |
|||
const int tsHeightIndex = 13; |
|||
const int tsLocaleIndex = 14; |
|||
const int tsBackgroundIndex = 15; |
|||
const int tsForegroundIndex = 16; |
|||
const int tsTextShadowsIndex = 17; |
|||
const int tsFontFeaturesIndex = 18; |
|||
|
|||
const int tsColorMask = 1 << tsColorIndex; |
|||
const int tsTextDecorationMask = 1 << tsTextDecorationIndex; |
|||
const int tsTextDecorationColorMask = 1 << tsTextDecorationColorIndex; |
|||
const int tsTextDecorationStyleMask = 1 << tsTextDecorationStyleIndex; |
|||
const int tsTextDecorationThicknessMask = 1 << tsTextDecorationThicknessIndex; |
|||
const int tsFontWeightMask = 1 << tsFontWeightIndex; |
|||
const int tsFontStyleMask = 1 << tsFontStyleIndex; |
|||
const int tsTextBaselineMask = 1 << tsTextBaselineIndex; |
|||
const int tsFontFamilyMask = 1 << tsFontFamilyIndex; |
|||
const int tsFontSizeMask = 1 << tsFontSizeIndex; |
|||
const int tsLetterSpacingMask = 1 << tsLetterSpacingIndex; |
|||
const int tsWordSpacingMask = 1 << tsWordSpacingIndex; |
|||
const int tsHeightMask = 1 << tsHeightIndex; |
|||
const int tsLocaleMask = 1 << tsLocaleIndex; |
|||
const int tsBackgroundMask = 1 << tsBackgroundIndex; |
|||
const int tsForegroundMask = 1 << tsForegroundIndex; |
|||
const int tsTextShadowsMask = 1 << tsTextShadowsIndex; |
|||
const int tsFontFeaturesMask = 1 << tsFontFeaturesIndex; |
|||
namespace { |
|||
const int tsColorIndex = 1; |
|||
const int tsTextDecorationIndex = 2; |
|||
const int tsTextDecorationColorIndex = 3; |
|||
const int tsTextDecorationStyleIndex = 4; |
|||
const int tsFontWeightIndex = 5; |
|||
const int tsFontStyleIndex = 6; |
|||
const int tsTextBaselineIndex = 7; |
|||
const int tsTextDecorationThicknessIndex = 8; |
|||
const int tsFontFamilyIndex = 9; |
|||
const int tsFontSizeIndex = 10; |
|||
const int tsLetterSpacingIndex = 11; |
|||
const int tsWordSpacingIndex = 12; |
|||
const int tsHeightIndex = 13; |
|||
const int tsLocaleIndex = 14; |
|||
const int tsBackgroundIndex = 15; |
|||
const int tsForegroundIndex = 16; |
|||
const int tsTextShadowsIndex = 17; |
|||
const int tsFontFeaturesIndex = 18; |
|||
// ParagraphStyle
|
|||
const int tsColorMask = 1 << tsColorIndex; |
|||
const int tsTextDecorationMask = 1 << tsTextDecorationIndex; |
|||
const int tsTextDecorationColorMask = 1 << tsTextDecorationColorIndex; |
|||
const int tsTextDecorationStyleMask = 1 << tsTextDecorationStyleIndex; |
|||
const int tsTextDecorationThicknessMask = 1 << tsTextDecorationThicknessIndex; |
|||
const int tsFontWeightMask = 1 << tsFontWeightIndex; |
|||
const int tsFontStyleMask = 1 << tsFontStyleIndex; |
|||
const int tsTextBaselineMask = 1 << tsTextBaselineIndex; |
|||
const int tsFontFamilyMask = 1 << tsFontFamilyIndex; |
|||
const int tsFontSizeMask = 1 << tsFontSizeIndex; |
|||
const int tsLetterSpacingMask = 1 << tsLetterSpacingIndex; |
|||
const int tsWordSpacingMask = 1 << tsWordSpacingIndex; |
|||
const int tsHeightMask = 1 << tsHeightIndex; |
|||
const int tsLocaleMask = 1 << tsLocaleIndex; |
|||
const int tsBackgroundMask = 1 << tsBackgroundIndex; |
|||
const int tsForegroundMask = 1 << tsForegroundIndex; |
|||
const int tsTextShadowsMask = 1 << tsTextShadowsIndex; |
|||
const int tsFontFeaturesMask = 1 << tsFontFeaturesIndex; |
|||
const int psTextAlignIndex = 1; |
|||
const int psTextDirectionIndex = 2; |
|||
const int psFontWeightIndex = 3; |
|||
const int psFontStyleIndex = 4; |
|||
const int psMaxLinesIndex = 5; |
|||
const int psTextHeightBehaviorIndex = 6; |
|||
const int psFontFamilyIndex = 7; |
|||
const int psFontSizeIndex = 8; |
|||
const int psHeightIndex = 9; |
|||
const int psStrutStyleIndex = 10; |
|||
const int psEllipsisIndex = 11; |
|||
const int psLocaleIndex = 12; |
|||
// ParagraphStyle
|
|||
const int psTextAlignMask = 1 << psTextAlignIndex; |
|||
const int psTextDirectionMask = 1 << psTextDirectionIndex; |
|||
const int psFontWeightMask = 1 << psFontWeightIndex; |
|||
const int psFontStyleMask = 1 << psFontStyleIndex; |
|||
const int psMaxLinesMask = 1 << psMaxLinesIndex; |
|||
const int psFontFamilyMask = 1 << psFontFamilyIndex; |
|||
const int psFontSizeMask = 1 << psFontSizeIndex; |
|||
const int psHeightMask = 1 << psHeightIndex; |
|||
const int psTextHeightBehaviorMask = 1 << psTextHeightBehaviorIndex; |
|||
const int psStrutStyleMask = 1 << psStrutStyleIndex; |
|||
const int psEllipsisMask = 1 << psEllipsisIndex; |
|||
const int psLocaleMask = 1 << psLocaleIndex; |
|||
const int psTextAlignIndex = 1; |
|||
const int psTextDirectionIndex = 2; |
|||
const int psFontWeightIndex = 3; |
|||
const int psFontStyleIndex = 4; |
|||
const int psMaxLinesIndex = 5; |
|||
const int psTextHeightBehaviorIndex = 6; |
|||
const int psFontFamilyIndex = 7; |
|||
const int psFontSizeIndex = 8; |
|||
const int psHeightIndex = 9; |
|||
const int psStrutStyleIndex = 10; |
|||
const int psEllipsisIndex = 11; |
|||
const int psLocaleIndex = 12; |
|||
// TextShadows decoding
|
|||
const int psTextAlignMask = 1 << psTextAlignIndex; |
|||
const int psTextDirectionMask = 1 << psTextDirectionIndex; |
|||
const int psFontWeightMask = 1 << psFontWeightIndex; |
|||
const int psFontStyleMask = 1 << psFontStyleIndex; |
|||
const int psMaxLinesMask = 1 << psMaxLinesIndex; |
|||
const int psFontFamilyMask = 1 << psFontFamilyIndex; |
|||
const int psFontSizeMask = 1 << psFontSizeIndex; |
|||
const int psHeightMask = 1 << psHeightIndex; |
|||
const int psTextHeightBehaviorMask = 1 << psTextHeightBehaviorIndex; |
|||
const int psStrutStyleMask = 1 << psStrutStyleIndex; |
|||
const int psEllipsisMask = 1 << psEllipsisIndex; |
|||
const int psLocaleMask = 1 << psLocaleIndex; |
|||
constexpr uint32_t kColorDefault = 0xFF000000; |
|||
constexpr uint32_t kBytesPerShadow = 16; |
|||
constexpr uint32_t kShadowPropertiesCount = 4; |
|||
constexpr uint32_t kColorOffset = 0; |
|||
constexpr uint32_t kXOffset = 1; |
|||
constexpr uint32_t kYOffset = 2; |
|||
constexpr uint32_t kBlurOffset = 3; |
|||
// TextShadows decoding
|
|||
// FontFeature decoding
|
|||
constexpr uint32_t kBytesPerFontFeature = 8; |
|||
constexpr uint32_t kFontFeatureTagLength = 4; |
|||
constexpr uint32_t kColorDefault = 0xFF000000; |
|||
constexpr uint32_t kBytesPerShadow = 16; |
|||
constexpr uint32_t kShadowPropertiesCount = 4; |
|||
constexpr uint32_t kColorOffset = 0; |
|||
constexpr uint32_t kXOffset = 1; |
|||
constexpr uint32_t kYOffset = 2; |
|||
constexpr uint32_t kBlurOffset = 3; |
|||
// Strut decoding
|
|||
const int sFontWeightIndex = 0; |
|||
const int sFontStyleIndex = 1; |
|||
const int sFontFamilyIndex = 2; |
|||
const int sFontSizeIndex = 3; |
|||
const int sHeightIndex = 4; |
|||
const int sLeadingIndex = 5; |
|||
const int sForceStrutHeightIndex = 6; |
|||
// FontFeature decoding
|
|||
constexpr uint32_t kBytesPerFontFeature = 8; |
|||
constexpr uint32_t kFontFeatureTagLength = 4; |
|||
const int sFontWeightMask = 1 << sFontWeightIndex; |
|||
const int sFontStyleMask = 1 << sFontStyleIndex; |
|||
const int sFontFamilyMask = 1 << sFontFamilyIndex; |
|||
const int sFontSizeMask = 1 << sFontSizeIndex; |
|||
const int sHeightMask = 1 << sHeightIndex; |
|||
const int sLeadingMask = 1 << sLeadingIndex; |
|||
const int sForceStrutHeightMask = 1 << sForceStrutHeightIndex; |
|||
// Strut decoding
|
|||
const int sFontWeightIndex = 0; |
|||
const int sFontStyleIndex = 1; |
|||
const int sFontFamilyIndex = 2; |
|||
const int sFontSizeIndex = 3; |
|||
const int sHeightIndex = 4; |
|||
const int sLeadingIndex = 5; |
|||
const int sForceStrutHeightIndex = 6; |
|||
} // namespace
|
|||
const int sFontWeightMask = 1 << sFontWeightIndex; |
|||
const int sFontStyleMask = 1 << sFontStyleIndex; |
|||
const int sFontFamilyMask = 1 << sFontFamilyIndex; |
|||
const int sFontSizeMask = 1 << sFontSizeIndex; |
|||
const int sHeightMask = 1 << sHeightIndex; |
|||
const int sLeadingMask = 1 << sLeadingIndex; |
|||
const int sForceStrutHeightMask = 1 << sForceStrutHeightIndex; |
|||
fml::RefPtr<ParagraphBuilder> ParagraphBuilder::create( |
|||
int* encoded, |
|||
uint8_t* strutData, |
|||
int strutDataSize, |
|||
const std::string& fontFamily, |
|||
const std::vector<std::string>& strutFontFamilies, |
|||
double fontSize, |
|||
double height, |
|||
const std::u16string& ellipsis, |
|||
const std::string& locale) { |
|||
return fml::MakeRefCounted<ParagraphBuilder>(encoded, strutData, strutDataSize, fontFamily, |
|||
strutFontFamilies, fontSize, |
|||
height, ellipsis, locale); |
|||
} |
|||
} // namespace
|
|||
void decodeTextShadows(uint8_t* shadows_data, int shadow_data_size, |
|||
std::vector<txt::TextShadow>& decoded_shadows) { |
|||
decoded_shadows.clear(); |
|||
fml::RefPtr<ParagraphBuilder> ParagraphBuilder::create( |
|||
int* encoded, uint8_t* strutData, int strutDataSize, |
|||
const std::string& fontFamily, |
|||
const std::vector<std::string>& strutFontFamilies, float fontSize, |
|||
float height, const std::u16string& ellipsis, const std::string& locale) { |
|||
return fml::MakeRefCounted<ParagraphBuilder>( |
|||
encoded, strutData, strutDataSize, fontFamily, strutFontFamilies, |
|||
fontSize, height, ellipsis, locale); |
|||
} |
|||
FML_CHECK(shadow_data_size % kBytesPerShadow == 0); |
|||
const uint32_t* uint_data = reinterpret_cast<const uint32_t*>(shadows_data); |
|||
const float* float_data = reinterpret_cast<const float*>(shadows_data); |
|||
void decodeTextShadows(uint8_t* shadows_data, int shadow_data_size, |
|||
std::vector<txt::TextShadow>& decoded_shadows) { |
|||
decoded_shadows.clear(); |
|||
size_t shadow_count = shadow_data_size / kBytesPerShadow; |
|||
size_t shadow_count_offset = 0; |
|||
for (size_t shadow_index = 0; shadow_index < shadow_count; ++shadow_index) { |
|||
shadow_count_offset = shadow_index * kShadowPropertiesCount; |
|||
SkColor color = |
|||
uint_data[shadow_count_offset + kColorOffset] ^ kColorDefault; |
|||
decoded_shadows.emplace_back( |
|||
color, |
|||
SkPoint::Make(float_data[shadow_count_offset + kXOffset], |
|||
float_data[shadow_count_offset + kYOffset]), |
|||
float_data[shadow_count_offset + kBlurOffset]); |
|||
} |
|||
} |
|||
FML_CHECK(shadow_data_size % kBytesPerShadow == 0); |
|||
const uint32_t* uint_data = reinterpret_cast<const uint32_t*>(shadows_data); |
|||
const float* float_data = reinterpret_cast<const float*>(shadows_data); |
|||
void decodeStrut(uint8_t* strut_data, int struct_data_size, |
|||
const std::vector<std::string>& strut_font_families, |
|||
txt::ParagraphStyle& paragraph_style) { |
|||
if (strut_data == nullptr) { |
|||
return; |
|||
} |
|||
size_t shadow_count = shadow_data_size / kBytesPerShadow; |
|||
size_t shadow_count_offset = 0; |
|||
for (size_t shadow_index = 0; shadow_index < shadow_count; ++shadow_index) { |
|||
shadow_count_offset = shadow_index * kShadowPropertiesCount; |
|||
SkColor color = |
|||
uint_data[shadow_count_offset + kColorOffset] ^ kColorDefault; |
|||
decoded_shadows.emplace_back( |
|||
color, |
|||
SkPoint::Make(float_data[shadow_count_offset + kXOffset], |
|||
float_data[shadow_count_offset + kYOffset]), |
|||
float_data[shadow_count_offset + kBlurOffset]); |
|||
} |
|||
} |
|||
if (struct_data_size == 0) { |
|||
return; |
|||
} |
|||
paragraph_style.strut_enabled = true; |
|||
void decodeStrut(uint8_t* strut_data, int struct_data_size, |
|||
const std::vector<std::string>& strut_font_families, |
|||
txt::ParagraphStyle& paragraph_style) { |
|||
if (strut_data == nullptr) { |
|||
return; |
|||
} |
|||
const uint8_t* uint8_data = static_cast<const uint8_t*>(strut_data); |
|||
uint8_t mask = uint8_data[0]; |
|||
if (struct_data_size == 0) { |
|||
return; |
|||
} |
|||
paragraph_style.strut_enabled = true; |
|||
// Data is stored in order of increasing size, eg, 8 bit ints will be before
|
|||
// any 32 bit ints. In addition, the order of decoding is the same order
|
|||
// as it is encoded, and the order is used to maintain consistency.
|
|||
size_t byte_count = 1; |
|||
if (mask & sFontWeightMask) { |
|||
paragraph_style.strut_font_weight = |
|||
static_cast<txt::FontWeight>(uint8_data[byte_count++]); |
|||
} |
|||
if (mask & sFontStyleMask) { |
|||
paragraph_style.strut_font_style = |
|||
static_cast<txt::FontStyle>(uint8_data[byte_count++]); |
|||
} |
|||
const uint8_t* uint8_data = static_cast<const uint8_t*>(strut_data); |
|||
uint8_t mask = uint8_data[0]; |
|||
std::vector<float> float_data; |
|||
float_data.resize((struct_data_size - byte_count) / 4); |
|||
memcpy(float_data.data(), |
|||
reinterpret_cast<const char*>(strut_data) + byte_count, |
|||
struct_data_size - byte_count); |
|||
size_t float_count = 0; |
|||
if (mask & sFontSizeMask) { |
|||
paragraph_style.strut_font_size = float_data[float_count++]; |
|||
} |
|||
if (mask & sHeightMask) { |
|||
paragraph_style.strut_height = float_data[float_count++]; |
|||
paragraph_style.strut_has_height_override = true; |
|||
} |
|||
if (mask & sLeadingMask) { |
|||
paragraph_style.strut_leading = float_data[float_count++]; |
|||
} |
|||
if (mask & sForceStrutHeightMask) { |
|||
// The boolean is stored as the last bit in the bitmask.
|
|||
paragraph_style.force_strut_height = (mask & 1 << 7) != 0; |
|||
} |
|||
// Data is stored in order of increasing size, eg, 8 bit ints will be before
|
|||
// any 32 bit ints. In addition, the order of decoding is the same order
|
|||
// as it is encoded, and the order is used to maintain consistency.
|
|||
size_t byte_count = 1; |
|||
if (mask & sFontWeightMask) { |
|||
paragraph_style.strut_font_weight = |
|||
static_cast<txt::FontWeight>(uint8_data[byte_count++]); |
|||
} |
|||
if (mask & sFontStyleMask) { |
|||
paragraph_style.strut_font_style = |
|||
static_cast<txt::FontStyle>(uint8_data[byte_count++]); |
|||
} |
|||
if (mask & sFontFamilyMask) { |
|||
paragraph_style.strut_font_families = strut_font_families; |
|||
} |
|||
else { |
|||
// Provide an empty font name so that the platform default font will be
|
|||
// used.
|
|||
paragraph_style.strut_font_families.push_back(""); |
|||
} |
|||
} |
|||
std::vector<float> float_data; |
|||
float_data.resize((struct_data_size - byte_count) / 4); |
|||
memcpy(float_data.data(), |
|||
reinterpret_cast<const char*>(strut_data) + byte_count, |
|||
struct_data_size - byte_count); |
|||
size_t float_count = 0; |
|||
if (mask & sFontSizeMask) { |
|||
paragraph_style.strut_font_size = float_data[float_count++]; |
|||
} |
|||
if (mask & sHeightMask) { |
|||
paragraph_style.strut_height = float_data[float_count++]; |
|||
paragraph_style.strut_has_height_override = true; |
|||
} |
|||
if (mask & sLeadingMask) { |
|||
paragraph_style.strut_leading = float_data[float_count++]; |
|||
} |
|||
if (mask & sForceStrutHeightMask) { |
|||
// The boolean is stored as the last bit in the bitmask.
|
|||
paragraph_style.force_strut_height = (mask & 1 << 7) != 0; |
|||
} |
|||
ParagraphBuilder::ParagraphBuilder( |
|||
int* encoded, |
|||
uint8_t* strutData, |
|||
int strutData_size, |
|||
const std::string& fontFamily, |
|||
const std::vector<std::string>& strutFontFamilies, |
|||
double fontSize, |
|||
double height, |
|||
const std::u16string& ellipsis, |
|||
const std::string& locale) { |
|||
if (mask & sFontFamilyMask) { |
|||
paragraph_style.strut_font_families = strut_font_families; |
|||
} else { |
|||
// Provide an empty font name so that the platform default font will be
|
|||
// used.
|
|||
paragraph_style.strut_font_families.push_back(""); |
|||
} |
|||
} |
|||
int32_t mask = encoded[0]; |
|||
txt::ParagraphStyle style; |
|||
ParagraphBuilder::ParagraphBuilder( |
|||
int* encoded, uint8_t* strutData, int strutData_size, |
|||
const std::string& fontFamily, |
|||
const std::vector<std::string>& strutFontFamilies, float fontSize, |
|||
float height, const std::u16string& ellipsis, const std::string& locale) { |
|||
int32_t mask = encoded[0]; |
|||
txt::ParagraphStyle style; |
|||
if (mask & psTextAlignMask) { |
|||
style.text_align = txt::TextAlign(encoded[psTextAlignIndex]); |
|||
} |
|||
if (mask & psTextAlignMask) { |
|||
style.text_align = txt::TextAlign(encoded[psTextAlignIndex]); |
|||
} |
|||
if (mask & psTextDirectionMask) { |
|||
style.text_direction = txt::TextDirection(encoded[psTextDirectionIndex]); |
|||
} |
|||
if (mask & psTextDirectionMask) { |
|||
style.text_direction = txt::TextDirection(encoded[psTextDirectionIndex]); |
|||
} |
|||
if (mask & psFontWeightMask) { |
|||
style.font_weight = |
|||
static_cast<txt::FontWeight>(encoded[psFontWeightIndex]); |
|||
} |
|||
if (mask & psFontWeightMask) { |
|||
style.font_weight = |
|||
static_cast<txt::FontWeight>(encoded[psFontWeightIndex]); |
|||
} |
|||
if (mask & psFontStyleMask) { |
|||
style.font_style = static_cast<txt::FontStyle>(encoded[psFontStyleIndex]); |
|||
} |
|||
if (mask & psFontStyleMask) { |
|||
style.font_style = static_cast<txt::FontStyle>(encoded[psFontStyleIndex]); |
|||
} |
|||
if (mask & psFontFamilyMask) { |
|||
style.font_family = fontFamily; |
|||
} |
|||
if (mask & psFontFamilyMask) { |
|||
style.font_family = fontFamily; |
|||
} |
|||
if (mask & psFontSizeMask) { |
|||
style.font_size = fontSize; |
|||
} |
|||
if (mask & psFontSizeMask) { |
|||
style.font_size = fontSize; |
|||
} |
|||
if (mask & psHeightMask) { |
|||
style.height = height; |
|||
style.has_height_override = true; |
|||
} |
|||
if (mask & psHeightMask) { |
|||
style.height = height; |
|||
style.has_height_override = true; |
|||
} |
|||
if (mask & psTextHeightBehaviorMask) { |
|||
style.text_height_behavior = encoded[psTextHeightBehaviorIndex]; |
|||
} |
|||
if (mask & psTextHeightBehaviorMask) { |
|||
style.text_height_behavior = encoded[psTextHeightBehaviorIndex]; |
|||
} |
|||
if (mask & psStrutStyleMask) { |
|||
decodeStrut(strutData, strutData_size, strutFontFamilies, style); |
|||
} |
|||
if (mask & psStrutStyleMask) { |
|||
decodeStrut(strutData, strutData_size, strutFontFamilies, style); |
|||
} |
|||
if (mask & psMaxLinesMask) { |
|||
style.max_lines = encoded[psMaxLinesIndex]; |
|||
} |
|||
if (mask & psMaxLinesMask) { |
|||
style.max_lines = encoded[psMaxLinesIndex]; |
|||
} |
|||
if (mask & psEllipsisMask) { |
|||
style.ellipsis = ellipsis; |
|||
} |
|||
if (mask & psEllipsisMask) { |
|||
style.ellipsis = ellipsis; |
|||
} |
|||
if (mask & psLocaleMask) { |
|||
style.locale = locale; |
|||
} |
|||
if (mask & psLocaleMask) { |
|||
style.locale = locale; |
|||
} |
|||
FontCollection& font_collection = |
|||
UIMonoState::Current()->window()->client()->GetFontCollection(); |
|||
FontCollection& font_collection = |
|||
UIMonoState::Current()->window()->client()->GetFontCollection(); |
|||
m_paragraphBuilder = |
|||
FLUTTER_PARAGRAPH_BUILDER(style, font_collection.GetFontCollection()); |
|||
} |
|||
m_paragraphBuilder = |
|||
FLUTTER_PARAGRAPH_BUILDER(style, font_collection.GetFontCollection()); |
|||
} |
|||
ParagraphBuilder::~ParagraphBuilder() = default; |
|||
ParagraphBuilder::~ParagraphBuilder() = default; |
|||
void decodeFontFeatures(uint8_t* font_features_data, int font_features_data_size, |
|||
txt::FontFeatures& font_features) { |
|||
uint8_t* byte_data(font_features_data); |
|||
FML_CHECK(font_features_data_size % kBytesPerFontFeature == 0); |
|||
void decodeFontFeatures(uint8_t* font_features_data, |
|||
int font_features_data_size, |
|||
txt::FontFeatures& font_features) { |
|||
uint8_t* byte_data(font_features_data); |
|||
FML_CHECK(font_features_data_size % kBytesPerFontFeature == 0); |
|||
size_t feature_count = font_features_data_size / kBytesPerFontFeature; |
|||
const char* char_data = reinterpret_cast<const char*>(font_features_data); |
|||
|
|||
for (size_t feature_index = 0; feature_index < feature_count; |
|||
++feature_index) { |
|||
size_t feature_offset = feature_index * kBytesPerFontFeature; |
|||
const char* feature_bytes = |
|||
char_data + feature_offset; |
|||
std::string tag(feature_bytes, kFontFeatureTagLength); |
|||
int32_t value = *(reinterpret_cast<const int32_t*>(feature_bytes + |
|||
kFontFeatureTagLength)); |
|||
font_features.SetFeature(tag, value); |
|||
} |
|||
} |
|||
|
|||
void ParagraphBuilder::pushStyle( |
|||
int* encoded, |
|||
int encodedSize, |
|||
char** fontFamilies, |
|||
int fontFamiliesSize, |
|||
double fontSize, |
|||
double letterSpacing, |
|||
double wordSpacing, |
|||
double height, |
|||
double decorationThickness, |
|||
const std::string& locale, |
|||
void** background_objects, |
|||
uint8_t* background_data, |
|||
void** foreground_objects, |
|||
uint8_t* foreground_data, |
|||
uint8_t* shadows_data, |
|||
int shadow_data_size, |
|||
uint8_t* font_features_data, |
|||
int font_feature_data_size) { |
|||
size_t feature_count = font_features_data_size / kBytesPerFontFeature; |
|||
const char* char_data = reinterpret_cast<const char*>(font_features_data); |
|||
FML_DCHECK(encodedSize == 8); |
|||
for (size_t feature_index = 0; feature_index < feature_count; |
|||
++feature_index) { |
|||
size_t feature_offset = feature_index * kBytesPerFontFeature; |
|||
const char* feature_bytes = char_data + feature_offset; |
|||
std::string tag(feature_bytes, kFontFeatureTagLength); |
|||
int32_t value = *(reinterpret_cast<const int32_t*>(feature_bytes + |
|||
kFontFeatureTagLength)); |
|||
font_features.SetFeature(tag, value); |
|||
} |
|||
} |
|||
int32_t mask = encoded[0]; |
|||
void ParagraphBuilder::pushStyle( |
|||
int* encoded, int encodedSize, char** fontFamilies, int fontFamiliesSize, |
|||
float fontSize, float letterSpacing, float wordSpacing, float height, |
|||
float decorationThickness, const std::string& locale, |
|||
void** background_objects, uint8_t* background_data, |
|||
void** foreground_objects, uint8_t* foreground_data, uint8_t* shadows_data, |
|||
int shadow_data_size, uint8_t* font_features_data, |
|||
int font_feature_data_size) { |
|||
FML_DCHECK(encodedSize == 8); |
|||
// Set to use the properties of the previous style if the property is not
|
|||
// explicitly given.
|
|||
txt::TextStyle style = m_paragraphBuilder->PeekStyle(); |
|||
int32_t mask = encoded[0]; |
|||
// Only change the style property from the previous value if a new explicitly
|
|||
// set value is available
|
|||
if (mask & tsColorMask) { |
|||
style.color = encoded[tsColorIndex]; |
|||
} |
|||
// Set to use the properties of the previous style if the property is not
|
|||
// explicitly given.
|
|||
txt::TextStyle style = m_paragraphBuilder->PeekStyle(); |
|||
if (mask & tsTextDecorationMask) { |
|||
style.decoration = |
|||
static_cast<txt::TextDecoration>(encoded[tsTextDecorationIndex]); |
|||
} |
|||
// Only change the style property from the previous value if a new explicitly
|
|||
// set value is available
|
|||
if (mask & tsColorMask) { |
|||
style.color = encoded[tsColorIndex]; |
|||
} |
|||
if (mask & tsTextDecorationColorMask) { |
|||
style.decoration_color = encoded[tsTextDecorationColorIndex]; |
|||
} |
|||
if (mask & tsTextDecorationMask) { |
|||
style.decoration = |
|||
static_cast<txt::TextDecoration>(encoded[tsTextDecorationIndex]); |
|||
} |
|||
if (mask & tsTextDecorationStyleMask) { |
|||
style.decoration_style = static_cast<txt::TextDecorationStyle>( |
|||
encoded[tsTextDecorationStyleIndex]); |
|||
} |
|||
if (mask & tsTextDecorationColorMask) { |
|||
style.decoration_color = encoded[tsTextDecorationColorIndex]; |
|||
} |
|||
if (mask & tsTextDecorationThicknessMask) { |
|||
style.decoration_thickness_multiplier = decorationThickness; |
|||
} |
|||
if (mask & tsTextDecorationStyleMask) { |
|||
style.decoration_style = static_cast<txt::TextDecorationStyle>( |
|||
encoded[tsTextDecorationStyleIndex]); |
|||
} |
|||
if (mask & tsTextBaselineMask) { |
|||
// TODO(abarth): Implement TextBaseline. The CSS version of this
|
|||
// property wasn't wired up either.
|
|||
} |
|||
if (mask & tsTextDecorationThicknessMask) { |
|||
style.decoration_thickness_multiplier = decorationThickness; |
|||
} |
|||
if (mask & (tsFontWeightMask | tsFontStyleMask | tsFontSizeMask | |
|||
tsLetterSpacingMask | tsWordSpacingMask)) { |
|||
if (mask & tsFontWeightMask) |
|||
style.font_weight = |
|||
static_cast<txt::FontWeight>(encoded[tsFontWeightIndex]); |
|||
if (mask & tsTextBaselineMask) { |
|||
// TODO(abarth): Implement TextBaseline. The CSS version of this
|
|||
// property wasn't wired up either.
|
|||
} |
|||
if (mask & tsFontStyleMask) |
|||
style.font_style = static_cast<txt::FontStyle>(encoded[tsFontStyleIndex]); |
|||
if (mask & (tsFontWeightMask | tsFontStyleMask | tsFontSizeMask | |
|||
tsLetterSpacingMask | tsWordSpacingMask)) { |
|||
if (mask & tsFontWeightMask) |
|||
style.font_weight = |
|||
static_cast<txt::FontWeight>(encoded[tsFontWeightIndex]); |
|||
if (mask & tsFontSizeMask) |
|||
style.font_size = fontSize; |
|||
if (mask & tsFontStyleMask) |
|||
style.font_style = static_cast<txt::FontStyle>(encoded[tsFontStyleIndex]); |
|||
if (mask & tsLetterSpacingMask) |
|||
style.letter_spacing = letterSpacing; |
|||
if (mask & tsFontSizeMask) style.font_size = fontSize; |
|||
if (mask & tsWordSpacingMask) |
|||
style.word_spacing = wordSpacing; |
|||
} |
|||
if (mask & tsLetterSpacingMask) style.letter_spacing = letterSpacing; |
|||
if (mask & tsHeightMask) { |
|||
style.height = height; |
|||
style.has_height_override = true; |
|||
} |
|||
if (mask & tsWordSpacingMask) style.word_spacing = wordSpacing; |
|||
} |
|||
if (mask & tsLocaleMask) { |
|||
style.locale = locale; |
|||
} |
|||
if (mask & tsHeightMask) { |
|||
style.height = height; |
|||
style.has_height_override = true; |
|||
} |
|||
if (mask & tsBackgroundMask) { |
|||
Paint background(background_objects, background_data); |
|||
if (background.paint()) { |
|||
style.has_background = true; |
|||
style.background = *background.paint(); |
|||
} |
|||
} |
|||
if (mask & tsLocaleMask) { |
|||
style.locale = locale; |
|||
} |
|||
if (mask & tsForegroundMask) { |
|||
Paint foreground(foreground_objects, foreground_data); |
|||
if (foreground.paint()) { |
|||
style.has_foreground = true; |
|||
style.foreground = *foreground.paint(); |
|||
} |
|||
} |
|||
if (mask & tsBackgroundMask) { |
|||
Paint background(background_objects, background_data); |
|||
if (background.paint()) { |
|||
style.has_background = true; |
|||
style.background = *background.paint(); |
|||
} |
|||
} |
|||
if (mask & tsTextShadowsMask) { |
|||
decodeTextShadows(shadows_data, shadow_data_size, style.text_shadows); |
|||
} |
|||
if (mask & tsForegroundMask) { |
|||
Paint foreground(foreground_objects, foreground_data); |
|||
if (foreground.paint()) { |
|||
style.has_foreground = true; |
|||
style.foreground = *foreground.paint(); |
|||
} |
|||
} |
|||
if (mask & tsFontFamilyMask) { |
|||
// The child style's font families override the parent's font families.
|
|||
// If the child's fonts are not available, then the font collection will
|
|||
// use the system fallback fonts (not the parent's fonts).
|
|||
style.font_families = std::vector<std::string>(fontFamilies, fontFamilies + fontFamiliesSize); |
|||
} |
|||
if (mask & tsTextShadowsMask) { |
|||
decodeTextShadows(shadows_data, shadow_data_size, style.text_shadows); |
|||
} |
|||
if (mask & tsFontFeaturesMask) { |
|||
decodeFontFeatures(font_features_data, font_feature_data_size, style.font_features); |
|||
} |
|||
if (mask & tsFontFamilyMask) { |
|||
// The child style's font families override the parent's font families.
|
|||
// If the child's fonts are not available, then the font collection will
|
|||
// use the system fallback fonts (not the parent's fonts).
|
|||
style.font_families = |
|||
std::vector<std::string>(fontFamilies, fontFamilies + fontFamiliesSize); |
|||
} |
|||
m_paragraphBuilder->PushStyle(style); |
|||
} |
|||
if (mask & tsFontFeaturesMask) { |
|||
decodeFontFeatures(font_features_data, font_feature_data_size, |
|||
style.font_features); |
|||
} |
|||
void ParagraphBuilder::pop() { |
|||
m_paragraphBuilder->Pop(); |
|||
} |
|||
m_paragraphBuilder->PushStyle(style); |
|||
} |
|||
const char* ParagraphBuilder::addText(const std::u16string& text) { |
|||
if (text.empty()) |
|||
return nullptr; |
|||
void ParagraphBuilder::pop() { m_paragraphBuilder->Pop(); } |
|||
// Use ICU to validate the UTF-16 input. Calling u_strToUTF8 with a null
|
|||
// output buffer will return U_BUFFER_OVERFLOW_ERROR if the input is well
|
|||
// formed.
|
|||
const UChar* text_ptr = reinterpret_cast<const UChar*>(text.data()); |
|||
UErrorCode error_code = U_ZERO_ERROR; |
|||
u_strToUTF8(nullptr, 0, nullptr, text_ptr, text.size(), &error_code); |
|||
if (error_code != U_BUFFER_OVERFLOW_ERROR) |
|||
return "string is not well-formed UTF-16"; |
|||
const char* ParagraphBuilder::addText(const std::u16string& text) { |
|||
if (text.empty()) return nullptr; |
|||
m_paragraphBuilder->AddText(text); |
|||
// Use ICU to validate the UTF-16 input. Calling u_strToUTF8 with a null
|
|||
// output buffer will return U_BUFFER_OVERFLOW_ERROR if the input is well
|
|||
// formed.
|
|||
const UChar* text_ptr = reinterpret_cast<const UChar*>(text.data()); |
|||
UErrorCode error_code = U_ZERO_ERROR; |
|||
u_strToUTF8(nullptr, 0, nullptr, text_ptr, text.size(), &error_code); |
|||
if (error_code != U_BUFFER_OVERFLOW_ERROR) |
|||
return "string is not well-formed UTF-16"; |
|||
return nullptr; |
|||
} |
|||
m_paragraphBuilder->AddText(text); |
|||
fml::RefPtr<Paragraph> ParagraphBuilder::build(/*Dart_Handle paragraph_handle*/) { |
|||
return Paragraph::Create(/*paragraph_handle,*/ m_paragraphBuilder->Build()); |
|||
|
|||
} |
|||
return nullptr; |
|||
} |
|||
const char* ParagraphBuilder::addPlaceholder( |
|||
double width, |
|||
double height, |
|||
unsigned alignment, |
|||
double baseline_offset, |
|||
unsigned baseline) { |
|||
txt::PlaceholderRun placeholder_run( |
|||
width, height, static_cast<txt::PlaceholderAlignment>(alignment), |
|||
static_cast<txt::TextBaseline>(baseline), baseline_offset); |
|||
fml::RefPtr<Paragraph> ParagraphBuilder::build( |
|||
/*Dart_Handle paragraph_handle*/) { |
|||
return Paragraph::Create(/*paragraph_handle,*/ m_paragraphBuilder->Build()); |
|||
} |
|||
m_paragraphBuilder->AddPlaceholder(placeholder_run); |
|||
const char* ParagraphBuilder::addPlaceholder(float width, float height, |
|||
unsigned alignment, |
|||
float baseline_offset, |
|||
unsigned baseline) { |
|||
txt::PlaceholderRun placeholder_run( |
|||
width, height, static_cast<txt::PlaceholderAlignment>(alignment), |
|||
static_cast<txt::TextBaseline>(baseline), baseline_offset); |
|||
return nullptr; |
|||
} |
|||
m_paragraphBuilder->AddPlaceholder(placeholder_run); |
|||
UIWIDGETS_API(ParagraphBuilder*) ParagraphBuilder_constructor( |
|||
int* encoded, |
|||
int encodedSize, |
|||
uint8_t* structData, |
|||
int structDataSize, |
|||
char* fontFamily, |
|||
char** structFontFamily, |
|||
int structFontFamilySize, |
|||
double fontSize, |
|||
double height, |
|||
char16_t* ellipsis, |
|||
char* locale) { |
|||
std::string fontFamily_s= fontFamily ? std::string(fontFamily) : ""; |
|||
auto structFamily_v = structFontFamily ? std::vector<std::string>(structFontFamily, structFontFamily + structFontFamilySize) : std::vector<std::string>(); |
|||
auto ellipsis_s = ellipsis ? std::u16string(ellipsis) : u""; |
|||
auto local_s = locale ? std::string(locale) : ""; |
|||
fml::RefPtr<ParagraphBuilder> paragraphBuilder = ParagraphBuilder::create( |
|||
encoded, |
|||
structData, |
|||
structDataSize, |
|||
fontFamily_s, |
|||
structFamily_v, |
|||
fontSize, |
|||
height, |
|||
ellipsis_s, |
|||
local_s |
|||
); |
|||
paragraphBuilder->AddRef(); |
|||
return paragraphBuilder.get(); |
|||
} |
|||
return nullptr; |
|||
} |
|||
UIWIDGETS_API(void) ParagraphBuilder_dispose(Canvas* ptr) { ptr->Release(); } |
|||
UIWIDGETS_API(ParagraphBuilder*) |
|||
ParagraphBuilder_constructor(int* encoded, int encodedSize, uint8_t* structData, |
|||
int structDataSize, char* fontFamily, |
|||
char** structFontFamily, int structFontFamilySize, |
|||
float fontSize, float height, char16_t* ellipsis, |
|||
char* locale) { |
|||
std::string fontFamily_s = fontFamily ? std::string(fontFamily) : ""; |
|||
auto structFamily_v = |
|||
structFontFamily |
|||
? std::vector<std::string>(structFontFamily, |
|||
structFontFamily + structFontFamilySize) |
|||
: std::vector<std::string>(); |
|||
auto ellipsis_s = ellipsis ? std::u16string(ellipsis) : u""; |
|||
auto local_s = locale ? std::string(locale) : ""; |
|||
fml::RefPtr<ParagraphBuilder> paragraphBuilder = ParagraphBuilder::create( |
|||
encoded, structData, structDataSize, fontFamily_s, structFamily_v, |
|||
fontSize, height, ellipsis_s, local_s); |
|||
paragraphBuilder->AddRef(); |
|||
return paragraphBuilder.get(); |
|||
} |
|||
UIWIDGETS_API(void) ParagraphBuilder_pushStyle( |
|||
ParagraphBuilder* ptr, |
|||
int* encoded, |
|||
int encodedSize, |
|||
char** fontFamilies, |
|||
int fontFamiliesSize, |
|||
double* fontSize, |
|||
double* letterSpacing, |
|||
double* wordSpacing, |
|||
double* height, |
|||
double* decorationThickness, |
|||
char* locale, |
|||
void** background_objects, |
|||
uint8_t* background_data, |
|||
void** foreground_objects, |
|||
uint8_t* foreground_data, |
|||
uint8_t* shadows_data, |
|||
int shadow_data_size, |
|||
uint8_t* font_features_data, |
|||
int font_feature_data_size |
|||
) { |
|||
UIWIDGETS_API(void) ParagraphBuilder_dispose(Canvas* ptr) { ptr->Release(); } |
|||
ptr->pushStyle(encoded, |
|||
encodedSize, |
|||
fontFamilies, |
|||
fontFamiliesSize, |
|||
*fontSize, |
|||
*letterSpacing, |
|||
*wordSpacing, |
|||
*height, |
|||
*decorationThickness, |
|||
locale, |
|||
background_objects, |
|||
background_data, |
|||
foreground_objects, |
|||
foreground_data, |
|||
shadows_data, |
|||
shadow_data_size, |
|||
font_features_data, |
|||
font_feature_data_size |
|||
); |
|||
} |
|||
UIWIDGETS_API(void) ParagraphBuilder_pop(ParagraphBuilder* ptr) { |
|||
ptr->pop(); |
|||
} |
|||
UIWIDGETS_API(void) |
|||
ParagraphBuilder_pushStyle(ParagraphBuilder* ptr, int* encoded, int encodedSize, |
|||
char** fontFamilies, int fontFamiliesSize, |
|||
float fontSize, float letterSpacing, |
|||
float wordSpacing, float height, |
|||
float decorationThickness, char* locale, |
|||
void** background_objects, uint8_t* background_data, |
|||
void** foreground_objects, uint8_t* foreground_data, |
|||
uint8_t* shadows_data, int shadow_data_size, |
|||
uint8_t* font_features_data, |
|||
int font_feature_data_size) { |
|||
ptr->pushStyle(encoded, encodedSize, fontFamilies, fontFamiliesSize, fontSize, |
|||
letterSpacing, wordSpacing, height, decorationThickness, |
|||
locale, background_objects, background_data, |
|||
foreground_objects, foreground_data, shadows_data, |
|||
shadow_data_size, font_features_data, font_feature_data_size); |
|||
} |
|||
UIWIDGETS_API(void) ParagraphBuilder_pop(ParagraphBuilder* ptr) { ptr->pop(); } |
|||
UIWIDGETS_API(const char*) ParagraphBuilder_addText(ParagraphBuilder* ptr, char16_t* text) { |
|||
return ptr->addText(std::u16string(text)); |
|||
} |
|||
UIWIDGETS_API(const char*) |
|||
ParagraphBuilder_addText(ParagraphBuilder* ptr, char16_t* text) { |
|||
return ptr->addText(std::u16string(text)); |
|||
} |
|||
UIWIDGETS_API(const char*) ParagraphBuilder_addPlaceholder(ParagraphBuilder* ptr, float width, float height, int alignment, float baselineOffset, unsigned baseline) { |
|||
return ptr->addPlaceholder(width, height, alignment, baselineOffset, baseline); |
|||
} |
|||
UIWIDGETS_API(const char*) |
|||
ParagraphBuilder_addPlaceholder(ParagraphBuilder* ptr, float width, |
|||
float height, int alignment, |
|||
float baselineOffset, unsigned baseline) { |
|||
return ptr->addPlaceholder(width, height, alignment, baselineOffset, |
|||
baseline); |
|||
} |
|||
UIWIDGETS_API(Paragraph*) ParagraphBuilder_build(ParagraphBuilder* ptr/*, IntPtr outParagraph*/) { |
|||
auto paragraph = ptr->build(); |
|||
paragraph->AddRef(); |
|||
return paragraph.get(); |
|||
} |
|||
} |
|||
UIWIDGETS_API(Paragraph*) |
|||
ParagraphBuilder_build(ParagraphBuilder* ptr /*, IntPtr outParagraph*/) { |
|||
auto paragraph = ptr->build(); |
|||
paragraph->AddRef(); |
|||
return paragraph.get(); |
|||
} |
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include <flutter/fml/memory/ref_counted.h> |
|||
#include <src\lib\ui\painting\canvas.h> |
|||
#include <flutter\third_party\txt\src\txt\paragraph.h> |
|||
#include "flutter/fml/memory/ref_counted.h" |
|||
#include "flutter/third_party/txt/src/txt/paragraph.h" |
|||
#include "utils.h" |
|||
#include "src/lib/ui/painting/canvas.h" |
|||
class ParagraphBuilder : public fml::RefCountedThreadSafe<ParagraphBuilder> { |
|||
FML_FRIEND_MAKE_REF_COUNTED(ParagraphBuilder); |
|||
class ParagraphBuilder : public fml::RefCountedThreadSafe<ParagraphBuilder> { |
|||
FML_FRIEND_MAKE_REF_COUNTED(ParagraphBuilder); |
|||
public: |
|||
static fml::RefPtr<ParagraphBuilder> create(int* encoded, uint8_t* structData, int structDataSize, const std::string& fontFamily, const std::vector<std::string>& strutFontFamilies, double fontSize, double height, const std::u16string& ellipsis, const std::string& locale); |
|||
|
|||
void pushStyle( |
|||
int* encoded, |
|||
int encodedSize, |
|||
char** fontFamilies, |
|||
int fontFamiliesSize, |
|||
double fontSize, |
|||
double letterSpacing, |
|||
double wordSpacing, |
|||
double height, |
|||
double decorationThickness, |
|||
const std::string& locale, |
|||
void** background_objects, |
|||
uint8_t* background_data, |
|||
void** foreground_objects, |
|||
uint8_t* foreground_data, |
|||
uint8_t* shadows_data, |
|||
int shadow_data_size, |
|||
uint8_t* font_features_data, |
|||
int font_feature_data_size); |
|||
public: |
|||
static fml::RefPtr<ParagraphBuilder> create( |
|||
int* encoded, uint8_t* structData, int structDataSize, |
|||
const std::string& fontFamily, |
|||
const std::vector<std::string>& strutFontFamilies, float fontSize, |
|||
float height, const std::u16string& ellipsis, const std::string& locale); |
|||
const char* addText(const std::u16string& text); |
|||
const char* addPlaceholder( |
|||
double width, |
|||
double height, |
|||
unsigned alignment, |
|||
double baseline_offset, |
|||
unsigned baseline); |
|||
fml::RefPtr<Paragraph> build(/*Dart_Handle paragraph_handle*/); |
|||
~ParagraphBuilder(); |
|||
void pushStyle(int* encoded, int encodedSize, char** fontFamilies, |
|||
int fontFamiliesSize, float fontSize, float letterSpacing, |
|||
float wordSpacing, float height, float decorationThickness, |
|||
const std::string& locale, void** background_objects, |
|||
uint8_t* background_data, void** foreground_objects, |
|||
uint8_t* foreground_data, uint8_t* shadows_data, |
|||
int shadow_data_size, uint8_t* font_features_data, |
|||
int font_feature_data_size); |
|||
void pop(); |
|||
const char* addText(const std::u16string& text); |
|||
const char* addPlaceholder(float width, float height, unsigned alignment, |
|||
float baseline_offset, unsigned baseline); |
|||
fml::RefPtr<Paragraph> build(/*Dart_Handle paragraph_handle*/); |
|||
~ParagraphBuilder(); |
|||
private: |
|||
explicit ParagraphBuilder( |
|||
int* encoded, |
|||
uint8_t* strutData, |
|||
int strutData_size, |
|||
const std::string& fontFamily, |
|||
const std::vector<std::string>& strutFontFamilies, |
|||
double fontSize, |
|||
double height, |
|||
const std::u16string& ellipsis, |
|||
const std::string& locale); |
|||
void pop(); |
|||
std::unique_ptr<txt::ParagraphBuilder> m_paragraphBuilder; |
|||
}; |
|||
} |
|||
private: |
|||
explicit ParagraphBuilder(int* encoded, uint8_t* strutData, |
|||
int strutData_size, const std::string& fontFamily, |
|||
const std::vector<std::string>& strutFontFamilies, |
|||
float fontSize, float height, |
|||
const std::u16string& ellipsis, |
|||
const std::string& locale); |
|||
|
|||
std::unique_ptr<txt::ParagraphBuilder> m_paragraphBuilder; |
|||
}; |
|||
} // namespace uiwidgets |
|
|||
using System; |
|||
using System.IO; |
|||
using Unity.UIWidgets.async2; |
|||
using Unity.UIWidgets.engine2; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.ui2; |
|||
using UnityEngine; |
|||
using Canvas = Unity.UIWidgets.ui2.Canvas; |
|||
using Color = Unity.UIWidgets.ui2.Color; |
|||
using Paint = Unity.UIWidgets.ui2.Paint; |
|||
using ParagraphBuilder = Unity.UIWidgets.ui2.ParagraphBuilder; |
|||
using ParagraphConstraints = Unity.UIWidgets.ui2.ParagraphConstraints; |
|||
using ParagraphStyle = Unity.UIWidgets.ui2.ParagraphStyle; |
|||
using Picture = Unity.UIWidgets.ui2.Picture; |
|||
using PictureRecorder = Unity.UIWidgets.ui2.PictureRecorder; |
|||
using Rect = Unity.UIWidgets.ui.Rect; |
|||
using SceneBuilder = Unity.UIWidgets.ui2.SceneBuilder; |
|||
using TextDecoration = Unity.UIWidgets.ui2.TextDecoration; |
|||
using TextDecorationStyle = Unity.UIWidgets.ui2.TextDecorationStyle; |
|||
using TextPosition = Unity.UIWidgets.ui2.TextPosition; |
|||
using Window = Unity.UIWidgets.ui2.Window; |
|||
|
|||
class TextTest : UIWidgetsPanel |
|||
{ |
|||
private bool check = true; |
|||
|
|||
void beginFrame(TimeSpan timeStamp) |
|||
{ |
|||
// The timeStamp argument to beginFrame indicates the timing information we
|
|||
// should use to clock our animations. It's important to use timeStamp rather
|
|||
// than reading the system time because we want all the parts of the system to
|
|||
// coordinate the timings of their animations. If each component read the
|
|||
// system clock independently, the animations that we processed later would be
|
|||
// slightly ahead of the animations we processed earlier.
|
|||
|
|||
// PAINT
|
|||
|
|||
Rect paintBounds = Offset.zero & (Window.instance.physicalSize / Window.instance.devicePixelRatio); |
|||
PictureRecorder recorder = new PictureRecorder(); |
|||
Canvas canvas = new Canvas(recorder, paintBounds); |
|||
canvas.translate(paintBounds.width / 2.0f, paintBounds.height / 2.0f); |
|||
|
|||
// Here we determine the rotation according to the timeStamp given to us by
|
|||
// the engine.
|
|||
float t = (float) timeStamp.TotalMilliseconds / 1800.0f; |
|||
canvas.rotate(Mathf.PI * (t % 2.0f)); |
|||
|
|||
var paint = new Paint(); |
|||
paint.color = Color.fromARGB(100, 100, 100, 0); |
|||
canvas.drawRect(Rect.fromLTRB(0, 0, 100.0f, 100.0f), paint); |
|||
Draw(canvas); |
|||
|
|||
Picture picture = recorder.endRecording(); |
|||
|
|||
// COMPOSITE
|
|||
|
|||
float devicePixelRatio = Window.instance.devicePixelRatio; |
|||
var deviceTransform = new float[16]; |
|||
deviceTransform[0] = devicePixelRatio; |
|||
deviceTransform[5] = devicePixelRatio; |
|||
deviceTransform[10] = 1.0f; |
|||
deviceTransform[15] = 1.0f; |
|||
SceneBuilder sceneBuilder = new SceneBuilder(); |
|||
|
|||
sceneBuilder.pushTransform(deviceTransform); |
|||
sceneBuilder.addPicture(Offset.zero, picture); |
|||
sceneBuilder.pop(); |
|||
Window.instance.render(sceneBuilder.build()); |
|||
|
|||
// After rendering the current frame of the animation, we ask the engine to
|
|||
// schedule another frame. The engine will call beginFrame again when its time
|
|||
// to produce the next frame.
|
|||
Window.instance.scheduleFrame(); |
|||
} |
|||
|
|||
void Draw(Canvas canvas) |
|||
{ |
|||
if (check) |
|||
{ |
|||
var robot_regular_bold = File.ReadAllBytes("./Assets/StreamingAssets/Roboto-BlackItalic.ttf"); |
|||
ui_.loadFontFromList(robot_regular_bold, "Roboto-RegularB").then(value => |
|||
{ |
|||
Debug.Log("finish loading"); |
|||
return FutureOr.nil; |
|||
}); |
|||
var robot_regular = File.ReadAllBytes("./Assets/StreamingAssets/Roboto-Italic.ttf"); |
|||
ui_.loadFontFromList(robot_regular, "Roboto-Regular"); |
|||
var ranchers = File.ReadAllBytes("./Assets/StreamingAssets/Ranchers-Regular.ttf"); |
|||
ui_.loadFontFromList(ranchers, "ranchers"); |
|||
check = false; |
|||
} |
|||
|
|||
var style = new ParagraphStyle(fontFamily: "Arial", height: 4); |
|||
|
|||
var pb = new ParagraphBuilder(style); |
|||
var ts_roboto_regular = new TextStyle( |
|||
color: new Color(0xF000000F), |
|||
decoration: TextDecoration.lineThrough, |
|||
decorationStyle: TextDecorationStyle.doubleLine, |
|||
fontFamily: "Roboto-Regular", |
|||
fontSize: 30, |
|||
height: 1.5f |
|||
); |
|||
pb.pushStyle(ts_roboto_regular); |
|||
pb.addText("just for test\n"); |
|||
var ts_roboto_regular_bold = new TextStyle( |
|||
color: new Color(0xF000000F), |
|||
decoration: TextDecoration.lineThrough, |
|||
decorationStyle: TextDecorationStyle.doubleLine, |
|||
fontFamily: "Roboto-RegularB", |
|||
fontSize: 30, |
|||
height: 1.5f |
|||
); |
|||
pb.pushStyle(ts_roboto_regular_bold); |
|||
pb.addText("just for test\n"); |
|||
var ts_rachers = new TextStyle( |
|||
color: new Color(0xF000000F), |
|||
decoration: TextDecoration.lineThrough, |
|||
decorationStyle: TextDecorationStyle.doubleLine, |
|||
fontFamily: "ranchers", |
|||
fontSize: 30, |
|||
height: 1.5f |
|||
); |
|||
pb.pushStyle(ts_rachers); |
|||
pb.addText("just for test\n"); |
|||
var ts = new TextStyle( |
|||
color: new Color(0xFFFF00F0), |
|||
decoration: TextDecoration.lineThrough, |
|||
decorationStyle: TextDecorationStyle.doubleLine, |
|||
fontFamily: "Arial", |
|||
fontSize: 30, |
|||
height: 1.5f |
|||
); |
|||
pb.pushStyle(ts); |
|||
pb.addText("just for test\n 中文测试 分段测试 分段测试 分段测试 分段测试 分段测试 分段测试 分段测试\n1234"); |
|||
var ts2 = new TextStyle( |
|||
decoration: TextDecoration.underline, |
|||
decorationStyle: TextDecorationStyle.dashed, |
|||
fontFamily: "Arial", |
|||
fontSize: 40, |
|||
height: 1.5f, |
|||
background: new Paint() |
|||
{ |
|||
color = new Color(0xAAFF7F00), |
|||
}, |
|||
foreground: new Paint() |
|||
{ |
|||
color = new Color(0xAAFFFF00) |
|||
} |
|||
); |
|||
pb.pushStyle(ts2); |
|||
pb.addText("test push one more style"); |
|||
pb.pop(); |
|||
pb.addText("test pop style"); |
|||
var p = pb.build(); |
|||
p.layout(new ParagraphConstraints(300)); |
|||
var wordBoundary = p.getWordBoundary(new TextPosition(10)); |
|||
Debug.Log(wordBoundary); |
|||
var positionForOffset = p.getPositionForOffset(new Offset(10, 1)); |
|||
Debug.Log(positionForOffset); |
|||
var lineBoundary = p.getLineBoundary(new TextPosition(10)); |
|||
Debug.Log(lineBoundary); |
|||
foreach (var textBox in p.getBoxesForPlaceholders()) |
|||
{ |
|||
Debug.Log($"{textBox.bottom} {textBox.direction} {textBox.left} {textBox.right}"); |
|||
} |
|||
|
|||
foreach (var textBox in p.getBoxesForRange(1, 20)) |
|||
{ |
|||
Debug.Log($"{textBox.bottom} {textBox.direction} {textBox.left} {textBox.right}"); |
|||
} |
|||
|
|||
foreach (var lineMetrics in p.computeLineMetrics()) |
|||
{ |
|||
Debug.Log($"{lineMetrics.height} {lineMetrics.lineNumber}"); |
|||
} |
|||
|
|||
canvas.drawParagraph(p, new Offset(-100, -100)); |
|||
} |
|||
|
|||
protected override void main() |
|||
{ |
|||
Window.instance.onBeginFrame = beginFrame; |
|||
Window.instance.scheduleFrame(); |
|||
} |
|||
} |
|
|||
|