• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Obtaining a Canvas and Displaying Drawing Results (C/C++)
2
3
4## When to Use
5
6Canvas provides the capability of drawing basic graphics on the screen. You can use Canvas to customize drawing effects to enhance user experience.
7
8Canvas is the core of graphics drawing. All drawing operations (including basic graphics drawing, text drawing, image drawing, and image transformation) mentioned in this chapter are based on Canvas.
9
10Currently, C/C++ can obtain Canvas in either of the following ways: Obtains the canvas that can be directly displayed on the screen and the canvas that can be directly displayed off the screen. The former can display the drawing result on the screen without additional operations after the drawing API is called, while the latter can display the drawing result by using the existing display method.
11
12
13## Available APIs
14
15The following table lists the common APIs for creating a Canvas. For details, see [drawing_canvas.h](../reference/apis-arkgraphics2d/drawing__canvas_8h.md).
16
17| Interface| Description|
18| -------- | -------- |
19| OH_Drawing_Canvas\* OH_Drawing_CanvasCreate (void) | Creates an **OH_Drawing_Canvas** object.|
20| void OH_Drawing_CanvasBind (OH_Drawing_Canvas\*, OH_Drawing_Bitmap\*) | Binds a bitmap to a canvas so that the content drawn on the canvas is output to the bitmap. (This process is called CPU rendering.)|
21| OH_Drawing_Canvas\* OH_Drawing_SurfaceGetCanvas (OH_Drawing_Surface \*) | Obtains a canvas from an **OH_Drawing_Surface** object.|
22
23
24## Obtaining the Canvas That Can Be Directly Displayed
25
26Obtains the canvas that can be directly displayed by using the XComponent.
27
281. Obtains the BufferHandle object from the NativeWindow corresponding to the XComponent. For details about APIs related to NativeWindow, see [_native_window](../reference/apis-arkgraphics2d/_native_window.md).
29
30   ```c++
31   uint64_t widht, height;
32   OHNativeWindow *nativeWindow; // The NativeWindow and its width and height need to be obtained from the XComponent.
33   int32_t usage = NATIVEBUFFER_USAGE_CPU_READ | NATIVEBUFFER_USAGE_CPU_WRITE | NATIVEBUFFER_USAGE_MEM_DMA;
34   int ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_USAGE, usage);
35   if (ret != 0) {
36       return;
37   }
38
39   struct NativeWindowBuffer *buffer = nullptr;
40   int fenceFd = 0;
41   ret = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &buffer, &fenceFd);
42   if (ret != 0) {
43       return;
44   }
45
46   BufferHandle* bufferHandle = OH_NativeWindow_GetBufferHandleFromNative(buffer);
47   ```
48
492. Obtains the corresponding memory address from BufferHandle.
50
51   ```c++
52   uint32_t* mappedAddr = static_cast<uint32_t *>(mmap(bufferHandle->virAddr, bufferHandle->size, PROT_READ | PROT_WRITE, MAP_SHARED, bufferHandle->fd, 0));
53   ```
54
553. Create a window canvas.
56
57   ```c++
58   OH_Drawing_Image_Info screenImageInfo = {static_cast<int32_t>(width), static_cast<int32_t>(height), COLOR_FORMAT_RGBA_8888, ALPHA_FORMAT_OPAQUE};
59   OH_Drawing_Bitmap* screenBitmap = OH_Drawing_BitmapCreateFromPixels(&screenImageInfo, mappedAddr, bufferHandle->stride);
60   OH_Drawing_Canvas* screenCanvas = OH_Drawing_CanvasCreate();
61   OH_Drawing_CanvasBind(screenCanvas, screenBitmap);
62   ```
63
644. Use the canvas obtained in the previous step to perform customized drawing operations, that is, the following content in this chapter.
65
665. Use XComponent to complete the display.
67
68   ```c++
69   Region region {nullptr, 0};
70   OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, buffer, fenceFd, region);
71   ```
72
73
74## Obtaining and Displaying the Off-Screen Canvas
75
76Currently, there are two methods of creating an off-screen Canvas: creating a CPU backend Canvas and creating a GPU backend Canvas. Both canvases depend on the XComponent to display the drawing result on the screen. Due to historical reasons, early Canvas is the CPU backend Canvas. Currently, the GPU backend Canvas is supported. The GPU has a stronger parallel computing capability and is more suitable for graphics drawing. However, the GPU backend Canvas does not support some scenarios. For example, in complex paths, the performance of drawing short texts is lower than that of the CPU backend Canvas.
77
78
79### Creating and Displaying a CPU Backend Canvas
80
81Currently, the drawing of C/C++ APIs depends on NativeWindow. The CPU backend Canvas needs to be drawn off the screen to generate a bitmap, and then the bitmap is displayed on the screen by using XComponent.
82
83
841. Import the dependent header files.
85
86   ```c++
87   #include <native_drawing/drawing_canvas.h>
88   #include <native_drawing/drawing_bitmap.h>
89   ```
90
912. Create a CPU-based Canvas. You need to create a bitmap object by calling OH_Drawing_BitmapCreate(). For details, see [PixelMap Drawing](pixelmap-drawing-c.md). Bind the bitmap to the Canvas by calling OH_Drawing_CanvasBind() so that the content drawn by the Canvas can be output to the bitmap.
92
93   ```c++
94   Creates an **OH_Drawing_Bitmap** object.
95   OH_Drawing_Bitmap* bitmap = OH_Drawing_BitmapCreate();
96   OH_Drawing_BitmapFormat cFormat{COLOR_FORMAT_RGBA_8888, ALPHA_FORMAT_PREMUL};
97   // Set the bitmap length and width as required.
98   uint32_t width = 800;
99   uint32_t height = 800;
100   // Initialize the bitmap.
101   OH_Drawing_BitmapBuild(bitmap, width, height, &cFormat);
102   // Create a Buffer object.
103   OH_Drawing_Canvas* bitmapCanvas = OH_Drawing_CanvasCreate();
104   // Bind the canvas to the bitmap. The content drawn by the canvas is output to the bound bitmap memory.
105   OH_Drawing_CanvasBind(bitmapCanvas, bitmap);
106   ```
107
108   To set the background color to white, perform the following steps:
109
110   ```c++
111   OH_Drawing_CanvasClear(bitmapCanvas, OH_Drawing_ColorSetArgb(0xFF, 0xFF, 0xFF, 0xFF));
112   ```
113
1143. Draw the bitmap created in the previous step to the [window canvas](#obtaining-the-canvas-that-can-be-directly-displayed).
115
116   ```c++
117   OH_Drawing_CanvasDrawBitmap(screenCanvas, bitmap, 0, 0);
118   ```
119
120
121### Creating and Displaying a GPU Backend Canvas
122
123The GPU backend Canvas indicates that the canvas is drawn based on the GPU. The parallel computing capability of the GPU is better than that of the CPU. The GPU backend Canvas is applicable to scenarios where images or areas are large. However, the GPU backend Canvas has a weak capability in drawing complex paths. Similar to the CPU backend Canvas. Currently, the drawing of the C/C++ interface depends on the XComponent. The GPU backend Canvas needs to be drawn off the screen and then displayed on the screen using the XComponent.
124
1251. Import the dependent header file.
126
127   ```c++
128   #include <native_drawing/drawing_gpu_context.h>
129   #include <native_drawing/drawing_surface.h>
130   ```
131
1322. Create a GPU backend Cnavas. The GPU backend Canvas needs to be obtained by using the Surface object. Therefore, you need to create a surface first. For details about the surface API, see [drawing_surface.h](../reference/apis-arkgraphics2d/drawing__surface_8h.md). Currently, drawing supports GPU backend drawing based on OpenGL. Therefore, you need to create a drawing context by calling OH_Drawing_GpuContextCreateFromGL, and then use the context as a parameter to create a surface, obtain the canvas from the surface by calling OH_Drawing_SurfaceGetCanvas.
133
134   ```c++
135   // Set the width and height as required.
136   int32_t cWidth = 800;
137   int32_t cHeight = 800;
138   // Set the image, including the width, height, color format, and transparency format.
139   OH_Drawing_Image_Info imageInfo = {cWidth, cHeight, COLOR_FORMAT_RGBA_8888, ALPHA_FORMAT_PREMUL};
140   // GPU context options
141   OH_Drawing_GpuContextOptions options{false};
142   // Create a drawing context that uses OpenGL (GL) as the GPU backend.
143   OH_Drawing_GpuContext *gpuContext = OH_Drawing_GpuContextCreateFromGL(options);
144   // Create a surface object.
145   OH_Drawing_Surface *surface = OH_Drawing_SurfaceCreateFromGpuContext(gpuContext, true, imageInfo);
146   // Create a canvas object.
147   OH_Drawing_Canvas* gpuCanvas = OH_Drawing_SurfaceGetCanvas(surface);
148   ```
149
150   To set the background color to white, perform the following steps:
151
152   ```c++
153   OH_Drawing_CanvasClear(gpuCanvas, OH_Drawing_ColorSetArgb(0xFF, 0xFF, 0xFF, 0xFF));
154   ```
155
1563. Copy the drawing result in the previous step to the [window canvas](#obtaining-the-canvas-that-can-be-directly-displayed).
157
158   ```c++
159   void* dstPixels = malloc(cWidth * cHeight * 4); // 4 for rgba
160   OH_Drawing_CanvasReadPixels(gpuCanvas, &imageInfo, dstPixels, 4 * cWidth, 0, 0);
161   OH_Drawing_Bitmap* bitmap = OH_Drawing_BitmapCreateFromPixels(&imageInfo, dstPixels, 4 * cWidth);
162   OH_Drawing_CanvasDrawBitmap(screenCanvas, bitmap, 0, 0);
163   ```
164