1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include <sstream> 17 18 #include <texgine/dynamic_file_font_provider.h> 19 #include <texgine/system_font_provider.h> 20 #include <texgine/typography_builder.h> 21 22 #include "feature_test_framework.h" 23 #include "text_define.h" 24 25 using namespace OHOS::Rosen::TextEngine; 26 27 namespace { 28 struct GlyphPosition { 29 double x = 0; 30 double y = 5; 31 TypographyStyle ys; 32 } g_datas[] { 33 { .x = -5, .y = -5 }, 34 { .x = -5, .y = 15 }, 35 { .x = 5, .y = -5 }, 36 { .x = -5, .y = 85 }, 37 { .x = 155, .y = -5 }, 38 { .x = 155, .y = 15 }, 39 { .x = 155, .y = 85 }, 40 { .x = 96, .y = 8 }, 41 { .x = 100, .y = 8 }, 42 { .x = 137, .y = 15 }, 43 { .x = 96, .y = 8, .ys = { .align = TextAlign::CENTER, }, }, 44 { .x = 100, .y = 8, .ys = { .align = TextAlign::CENTER, }, }, 45 { .x = 123, .y = 70, .ys = { .align = TextAlign::CENTER, }, }, 46 { .x = 22, .y = 70, .ys = { .align = TextAlign::CENTER, }, }, 47 { .x = 46, .y = 70, }, 48 { .x = 52, .y = 70, }, 49 { .x = 55, .y = 70, }, 50 { .x = 52, .y = 67, }, 51 }; 52 53 constexpr auto TEXT = "hello world hello world 你好世界 你好世界, hello openharmony, hello openharmony, 你好鸿蒙"; 54 55 class GlyphPositionTest : public TestFeature { 56 public: GlyphPositionTest()57 GlyphPositionTest() : TestFeature("GlyphPositionTest") 58 { 59 } 60 Layout()61 void Layout() override 62 { 63 TextStyle xs; 64 xs.fontFamilies = {"Segoe UI Emoji"}; 65 xs.fontSize = 14; // 14 means the font size 66 67 for (auto &data : g_datas) { 68 auto dfProvider = DynamicFileFontProvider::Create(); 69 dfProvider->LoadFont("Segoe UI Emoji", RESOURCE_PATH_PREFIX "seguiemj.ttf"); 70 auto fps = FontProviders::Create(); 71 fps->AppendFontProvider(dfProvider); 72 fps->AppendFontProvider(SystemFontProvider::GetInstance()); 73 74 auto builder = TypographyBuilder::Create(data.ys, std::move(fps)); 75 builder->PushStyle(xs); 76 builder->AppendSpan(TEXT); 77 builder->PopStyle(); 78 79 std::string emojiText = WOMAN SKIN1 ZWJ RED_HEART ZWJ MAN SKIN0; 80 builder->PushStyle(xs); 81 builder->AppendSpan(emojiText); 82 builder->PopStyle(); 83 84 auto onPaint = GetPaintFunc(data); 85 std::stringstream ss; 86 ss << "(" << data.x << ", " << data.y << ")"; 87 if (data.ys.align == TextAlign::CENTER) { 88 ss << " align(center)"; 89 } 90 91 auto typography = builder->Build(); 92 double widthLimit = 150.0; 93 typography->Layout(widthLimit); 94 typographies_.push_back({ 95 .typography = typography, 96 .comment = ss.str(), 97 .onPaint = onPaint, 98 }); 99 } 100 } 101 GetPaintFunc(const GlyphPosition & data)102 static std::function<void(const struct TypographyData &, TexgineCanvas &, double, double)> GetPaintFunc( 103 const GlyphPosition &data) 104 { 105 auto onPaint = [data](const struct TypographyData &tyData, TexgineCanvas &canvas, double x, double y) { 106 auto &typography = tyData.typography; 107 typography->Paint(canvas, x, y); 108 TexginePaint paint; 109 paint.SetAntiAlias(true); 110 paint.SetColor(0x7F00FF00); 111 paint.SetStrokeWidth(5); 112 canvas.DrawLine(x + data.x - 10, y + data.y, x + data.x + 10, y + data.y, paint); 113 canvas.DrawLine(x + data.x, y + data.y - 10, x + data.x, y + data.y + 10, paint); 114 paint.SetColor(0xFF00FF); 115 paint.SetAlpha(255 * 0.3); 116 canvas.Save(); 117 canvas.Translate(x, y); 118 auto ia = typography->GetGlyphIndexByCoordinate(data.x, data.y); 119 auto rects = typography->GetTextRectsByBoundary(Boundary{ia.index, ia.index + 1}, 120 TextRectHeightStyle::COVER_TOP_AND_BOTTOM, TextRectWidthStyle::TIGHT); 121 if (rects.size()) { 122 canvas.DrawRect(rects.back().rect, paint); 123 } 124 canvas.Restore(); 125 }; 126 127 return onPaint; 128 } 129 } g_test; 130 } // namespace 131