1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.. All rights reserved.
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 <cinttypes>
17 #include <codecvt>
18 #include <cstdio>
19 #include <cstdlib>
20 #include <fstream>
21 #include <iostream>
22 #include <locale>
23 #include <memory>
24 #include <securec.h>
25 #include <sstream>
26 #include <string>
27 #include <surface.h>
28 #include <unistd.h>
29 
30 #include "command/rs_base_node_command.h"
31 #include "command/rs_display_node_command.h"
32 #include "command/rs_surface_node_command.h"
33 #include "common/rs_common_def.h"
34 #include "core/transaction/rs_interfaces.h"
35 #include "core/ui/rs_display_node.h"
36 #include "core/ui/rs_surface_node.h"
37 #include "draw/canvas.h"
38 #include "draw/pen.h"
39 #include "foundation/graphic/graphic_2d/rosen/modules/render_service_base/src/platform/ohos/rs_surface_frame_ohos.h"
40 #include "foundation/graphic/graphic_2d/rosen/modules/render_service_base/src/platform/ohos/rs_surface_ohos.h"
41 #include "image/bitmap.h"
42 #include "pipeline/rs_render_result.h"
43 #include "pipeline/rs_render_thread.h"
44 #include "rosen_text/properties/text_style.h"
45 #include "rosen_text/properties/typography_properties.h"
46 #include "rosen_text/ui/font_collection.h"
47 #include "rosen_text/ui/typography.h"
48 #include "rosen_text/ui/typography_create.h"
49 #include "ui/rs_canvas_node.h"
50 #include "ui/rs_surface_extractor.h"
51 #include "ui/rs_ui_director.h"
52 
53 using namespace std;
54 using namespace OHOS;
55 using namespace Rosen;
56 using namespace rosen;
57 using namespace Drawing;
58 using namespace Media;
59 
TextToUtf16(std::string str)60 std::u16string TextToUtf16(std::string str)
61 {
62     return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> {}.from_bytes(str);
63 }
64 
DoDraw(uint8_t * addr,uint32_t width,uint32_t height,size_t index)65 void DoDraw(uint8_t *addr, uint32_t width, uint32_t height, size_t index)
66 {
67     Bitmap bitmapCache;
68     BitmapFormat format {COLORTYPE_RGBA_8888, ALPHATYPE_OPAQUE};
69     bitmapCache.Build(width, height, format);
70 
71     Canvas canvas;
72     canvas.Bind(bitmapCache);
73     canvas.Clear(Drawing::Color::COLOR_WHITE);
74     TypographyStyle typoStype;
75     typoStype.textDirection_ = TextDirection::LTR;
76     typoStype.textAlign_ = TextAlign::START;
77     typoStype.maxLines_ = 1000; // maxLines 1000
78     typoStype.locale_ = "en";
79     typoStype.wordBreakType_ = WordBreakType::WordBreakTypeBreakWord;
80     std::unique_ptr<TypographyCreate> builder = TypographyCreate::CreateRosenBuilder(
81         typoStype, FontCollection::GetInstance());
82     TextStyle textStyle;
83 
84     textStyle.fontFamilies_ = std::vector<std::string>(1, "Roboto");
85     textStyle.color_ = Drawing::Color::COLOR_BLACK;
86     builder->PushStyle(textStyle);
87     const std::string utf8 = "hello world!\n";
88 
89     const std::u16string u16Text = TextToUtf16(utf8);
90     builder->AddText(u16Text);
91     builder->Pop();
92     // layout
93     std::unique_ptr<rosen::Typography> typography;
94     typography = builder->Build();
95     if (typography == nullptr) {
96         LOGD("typography == nullptr");
97         return;
98     }
99     double lastLayoutMaxWidth = 1000.0; // width 1000.0
100     typography->Layout(lastLayoutMaxWidth);
101     typography->Paint(&canvas, 10.0, 15.0); // pos to paint 10.0, 15.0
102     constexpr uint32_t stride = 4;
103     int32_t addrSize = width * height * stride;
104     auto ret = memcpy_s(addr, addrSize, bitmapCache.GetPixels(), addrSize);
105     if (ret != EOK) {
106         LOGD("memcpy_s failed");
107     }
108 }
109 
DrawSurface(std::shared_ptr<RSSurfaceNode> surfaceNode,int32_t width,int32_t height,size_t index)110 void DrawSurface(std::shared_ptr<RSSurfaceNode> surfaceNode, int32_t width, int32_t height, size_t index)
111 {
112     sptr<OHOS::Surface> surface = surfaceNode->GetSurface();
113     if (surface == nullptr) {
114         return;
115     }
116 
117     sptr<OHOS::SurfaceBuffer> buffer;
118     int32_t releaseFence;
119     OHOS::BufferRequestConfig config = {
120         .width = width,
121         .height = height,
122         .strideAlignment = 0x8,
123         .format = GRAPHIC_PIXEL_FMT_RGBA_8888,
124         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
125     };
126 
127     OHOS::SurfaceError ret = surface->RequestBuffer(buffer, releaseFence, config);
128     LOGD("request buffer ret is: %{public}s", SurfaceErrorStr(ret).c_str());
129 
130     if (buffer == nullptr) {
131         LOGD("request buffer failed: buffer is nullptr");
132         return;
133     }
134     if (buffer->GetVirAddr() == nullptr) {
135         LOGD("get virAddr failed: virAddr is nullptr");
136         return;
137     }
138 
139     auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
140     LOGD("buffer width:%{public}d, height:%{public}d", buffer->GetWidth(), buffer->GetHeight());
141 
142     DoDraw(addr, buffer->GetWidth(), buffer->GetHeight(), index);
143     LOGD("DoDraw end");
144 
145     OHOS::BufferFlushConfig flushConfig = {
146         .damage = {
147             .w = buffer->GetWidth(),
148             .h = buffer->GetHeight(),
149         },
150     };
151     ret = surface->FlushBuffer(buffer, -1, flushConfig);
152     LOGD("draw pointer FlushBuffer ret is: %{public}s", SurfaceErrorStr(ret).c_str());
153 }
154 
CreateSurface()155 std::shared_ptr<RSSurfaceNode> CreateSurface()
156 {
157     RSSurfaceNodeConfig config;
158     return RSSurfaceNode::Create(config);
159 }
160 
main(int argc,char ** argv)161 int main(int argc, char** argv)
162 {
163     auto surfaceNode = CreateSurface();
164     RSDisplayNodeConfig config;
165     RSDisplayNode::SharedPtr displayNode = RSDisplayNode::Create(config);
166     for (size_t i = 0; i < 5; i++) { // Draw 5 times
167         sleep(2); // delay 2 second
168         displayNode->AddChild(surfaceNode, -1);
169         surfaceNode->SetBounds(0, 0, 2560, 1600); // Draw Range 2560, 1600
170         RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
171         DrawSurface(surfaceNode, 2560, 1600, i); // Draw Range 2560, 1600
172         sleep(4); // delay 4 second
173         displayNode->RemoveChild(surfaceNode);
174         RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
175     }
176     return 0;
177 }
178