oh-graphic-pixel-tests-generator
14
总安装量
5
周安装量
#23994
全站排名
安装命令
npx skills add https://github.com/openharmonyinsight/openharmony-skills --skill oh-graphic-pixel-tests-generator
Agent 安装分布
opencode
4
amp
2
kimi-cli
2
github-copilot
2
claude-code
2
Skill 文档
ç®å½
- æ¡æ¶æ¦è¿°
- æµè¯æµç¨è¯¦è§£
- æµè¯å®ç³»ç»
- 宿´APIåè
- åæ°é 置说æ
- æµè¯æ¨¡æ¿åº
- Drawing API åè
- æä½³å®è·µ
æ¡æ¶æ¦è¿°
æ ¸å¿åç
OH-å¾å½¢æµè¯æ¡æ¶åºäº åç´ çº§æ¯å¯¹ éªè¯å¾å½¢æ¸²ææ£ç¡®æ§ãæµè¯è¿è¡å¨çå®ç Rosen 渲æç¯å¢ä¸ï¼éè¿åå»ºåºæ¯å¾èç¹ãæ§è¡æ¸²æãæªå¾ä¿åæ¥å®ç°éªè¯ã
æ¶ææµç¨
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â æµè¯ç¨ä¾ (RSGraphicTest) â
â - å建æµè¯èç¹ â
â - 设置èç¹å±æ§ â
â - å½å¶ç»å¶å½ä»¤ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â RS客æ·ç«¯ (render_service_client) â
â - RSCanvasNode / RSSurfaceNode / RSDisplayNode â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â RSTransactionProxy::FlushImplicitTransaction() â
â - äºå¡æäº¤ï¼è§¦åIPCéä¿¡ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â RSæå¡ç«¯ (render_service) â
â - æ¥æ¶äºå¡ï¼æ´æ°æå¡ç«¯èç¹æ â
â - 渲æç®¡çº¿å¤ç â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â 2D Graphics (Drawing弿) â
â - Canvas ç»å¶å½ä»¤æ§è¡ â
â - GPU/Backend 渲æ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â DisplayManager::GetScreenshot() â
â - è·å渲æç»ææªå¾ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â PNG ä¿å â
â /data/local/graphic_test/<åç±»>/<æµè¯ç±»>_<æµè¯å>.png â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
æµè¯æ¨¡å¼
| æ¨¡å¼ | å® | æªå¾æ¹å¼ | ç¨é |
|---|---|---|---|
| AUTOMATIC | GRAPHIC_TEST |
èªå¨æªå¾ | æ ååè½æµè¯ï¼æµè¯ç»æèªå¨æªå¾ |
| MANUAL | GRAPHIC_N_TEST |
æå¨æªå¾ | éè¦æå¨æ§å¶æªå¾æ¶æº |
| DYNAMIC | GRAPHIC_D_TEST |
卿æªå¾ | æ¯æå½å¶åæ¾ç卿æµè¯ |
ç®å½ç»æ
graphic_test/
âââ graphic_test_framework/ # æµè¯æ¡æ¶
â âââ include/
â â âââ rs_graphic_test.h # æµè¯åºç±»
â â âââ rs_graphic_test_ext.h # æµè¯å®å®ä¹
â â âââ rs_graphic_test_img.h # å¾çè¾
å©å½æ°
â â âââ rs_graphic_test_utils.h # å·¥å
·å½æ°
â â âââ rs_graphic_test_director.h # æµè¯æ§å¶å¨
â âââ src/
â âââ rs_graphic_test.cpp # æ¡æ¶å®ç°
â
âââ test/ # æµè¯ç¨ä¾
â âââ open_capability/ # 弿¾è½åæµè¯
â âââ rs_perform_feature/ # æ§è½ç¹æ§æµè¯
â âââ drawing_engine/ # ç»å¶å¼ææµè¯
â âââ test_template/ # æµè¯æ¨¡æ¿
â
âââ BUILD.gn # æå»ºé
ç½®
æµè¯æµç¨è¯¦è§£
宿´çå½å¨æ
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â SetUpTestCase() [éæï¼æµè¯å¥ä»¶å¼å§æ¶æ§è¡ä¸æ¬¡] â
â â
â ⢠imageWriteId_ = 0 // éç½®æªå¾ID计æ°å¨ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â SetUp() [æ¯ä¸ªæµè¯ç¨ä¾æ§è¡å] â
â â
â 1. ShouldRunCurrentTest() â
â - æ ¹æ® --testType å --testMode åæ°è¿æ»¤æµè¯ â
â - 䏿»¡è¶³æ¡ä»¶åè·³è¿ (GTEST_SKIP) â
â â
â 2. å建æµè¯ Surface â
â RSSurfaceNode::Create(config, APP_WINDOW_NODE) â
â â SetBounds({0, 0, width, height}) â
â â SetFrame({0, 0, width, height}) â
â â SetBackgroundColor(0xffffffff) â
â â
â 3. BeforeEach() [ç¨æ·éå] â
â - SetScreenSize(width, height) â
â - SetSurfaceBounds(bounds) â
â - å è½½æµè¯èµæºç â
â â
â 4. 夿µè¯æ¨¡å¼å¤ç (isMultiple=true) â
â - 计ç®ç½æ ¼å¸å±: GetScreenCapacity() â
â - 设置èæå±å¹å°ºå¯¸: capacity.x * size.x â
â - 计ç®å½åæµè¯ä½ç½®: GetPos(testId) â
â - 设置 Surface ä½ç½®å°å¯¹åºç½æ ¼ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â æµè¯ç¨ä¾å½æ°ä½ â
â â
â 1. å建èç¹ â
â auto node = RSCanvasNode::Create(); â
â â
â 2. 设置èç¹å±æ§ â
â node->SetBounds({x, y, w, h}); â
â node->SetFrame({x, y, w, h}); â
â node->SetBackgroundColor(color); â
â â
â 3. æ·»å å°åºæ¯å¾ â
â GetRootNode()->AddChild(node); â
â â
â 4. 注åèç¹ [å¿
é¡»è°ç¨] â
â RegisterNode(node); // ä¿æèç¹å¼ç¨ï¼é²æ¢è¢«éæ¾ â
â â
â 5. å½å¶ç»å¶å½ä»¤ â
â auto drawing = node->BeginRecording(w, h); â
â drawing->DrawXXX(...); â
â node->FinishRecording(); â
â â
â 6. å·æ°äºå¡ â
â RSTransactionProxy::GetInstance()->FlushImplicitTransaction();â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â TearDown() [æ¯ä¸ªæµè¯ç¨ä¾æ§è¡å] â
â â
â 1. WaitOtherTest() â
â - 夿µè¯æ¨¡å¼: å»¶è¿æªå¾ç´å°æææµè¯å®æ â
â - åæµè¯æ¨¡å¼: ç´æ¥ç»§ç» â
â â
â 2. StartUIAnimation() â
â - å¯å¨å¹¶æ§è¡ææå¨ç» â
â â
â 3. FlushMessageAndWait(testCaseWaitTime) â
â - çå¾
渲æå®æ (é»è®¤ 1000ms) â
â â
â 4. WaitTimeout(normalWaitTime) â
â - é¢å¤çå¾
(é»è®¤ 10ms) â
â â
â 5. æ ¹æ®æµè¯æ¨¡å¼å¤ç â
â - MANUAL: WaitTimeout(manualTestWaitTime) [æå¨æ¨¡å¼çå¾
] â
â - AUTOMATIC/DYNAMIC: TestCaseCapture() [èªå¨æªå¾] â
â â
â 6. AfterEach() [ç¨æ·éå] â
â - ç¨æ·èªå®ä¹æ¸
ç â
â â
â 7. èµæºæ¸
ç â
â - ResetTestSurface() â
â - nodes_.clear() â
â - SendProfilerCommand("rssubtree_clear") â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â TearDownTestCase() [éæï¼æµè¯å¥ä»¶ç»ææ¶æ§è¡ä¸æ¬¡] â
â â¢ æ æä½ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
å ³é®æ¥éª¤è¯´æ
1. RegisterNode() çéè¦æ§
// RegisterNode() åäºä¸¤ä»¶äºï¼
// 1. å°èç¹æ·»å å° nodes_ åéï¼ä¿æ shared_ptr å¼ç¨
// 2. è°ç¨ GetRootNode()->RegisterNode(node) 注åå°æ ¹èç¹
void RegisterNode(std::shared_ptr<RSNode> node) {
nodes_.push_back(node); // ä¿æå¼ç¨
GetRootNode()->RegisterNode(node); // 注åå°æ
}
ä¸è°ç¨ RegisterNode() çåæï¼èç¹å¯è½è¢«æåéæ¾ï¼å¯¼è´æ¸²æé误æå´©æºã
2. 夿µè¯ç½æ ¼å¸å±
å½ä½¿ç¨ GRAPHIC_TESTS å®ï¼isMultiple=trueï¼æ¶ï¼
// 计ç®ç½æ ¼å®¹éï¼å°½éæ¥è¿æ£æ¹å½¢ï¼
// ä¾å¦ï¼12个æµè¯ â 4x3 ç½æ ¼
UIPoint GetScreenCapacity(int testCnt) {
int cl = 1; // åæ°
int num = 1;
while (num < testCnt) {
cl++;
num = cl * cl; // cl² >= testCnt
}
int rl = ceil(testCnt / cl); // è¡æ°
return {cl, rl};
}
// è®¡ç®æµè¯ä½ç½®
UIPoint GetPos(int id, int cl) {
int x = id % cl; // åç´¢å¼
int y = id / cl; // è¡ç´¢å¼
return {x, y};
}
æ¯ä¸ªæµè¯ç Surface ä¼è¢«æ¾ç½®å°èæå±å¹ç对åºç½æ ¼ä½ç½®ã
3. æªå¾è·¯å¾è§å
// è·¯å¾çæè§å
std::string GetImageSavePath(const std::string filePath) {
// filePath: /path/to/graphic_test/test/xxx/my_test.cpp
// æå: /test/xxx/
// ç»æ: /data/local/graphic_test/test/xxx/
// æç»æä»¶åæ ¼å¼ï¼
// /data/local/graphic_test/test/xxx/<æµè¯ç±»>_<æµè¯å>.png
}
4. äºå¡å·æ°æ¶æº
// FlushImplicitTransaction() 触åï¼
// 1. 客æ·ç«¯å½ä»¤æå
// 2. IPC åéå°æå¡ç«¯
// 3. æå¡ç«¯æ´æ°èç¹æ
// 4. è§¦åæ¸²æç®¡çº¿
// å¿
é¡»å¨ä»¥ä¸æä½åè°ç¨ï¼
// - èç¹å±æ§ä¿®æ¹å
// - ç»å¶å½ä»¤å½å¶å®æå
// - å¨ç»å¯å¨å
æµè¯å®ç³»ç»
å®å®ä¹å±å¼
// GRAPHIC_TEST å®å±å¼åçå®é
代ç
#define GRAPHIC_TEST(test_case_name, test_type, test_name) \
bool GTEST_TEST_UNIQUE_ID_##test_case_name##test_name##__LINE__ = \
OHOS::Rosen::TestDefManager::Instance().Regist( \
#test_case_name, #test_name, test_type, \
RSGraphicTestMode::AUTOMATIC, __FILE__, false); \
TEST_F(test_case_name, test_name)
æµè¯å®ç±»å
| å® | æµè¯æ¨¡å¼ | isMultiple | ç¨é |
|---|---|---|---|
GRAPHIC_TEST(TestCase, Type, Name) |
AUTOMATIC | false | æ åæµè¯ï¼èªå¨æªå¾ |
GRAPHIC_N_TEST(TestCase, Type, Name) |
MANUAL | false | æå¨æ¨¡å¼ï¼éæå¨æªå¾ |
GRAPHIC_D_TEST(TestCase, Type, Name) |
DYNAMIC | false | 卿忾æµè¯ |
GRAPHIC_TESTS(TestCase, Type, Name) |
AUTOMATIC | true | 夿µè¯ç½æ ¼å¸å± |
åæ°è¯´æ
GRAPHIC_TEST(æµè¯ç±»å, æµè¯ç±»å, æµè¯å½æ°å)
// æµè¯ç±»å: ç»§æ¿ RSGraphicTest çç±»å
// æµè¯ç±»å: RSGraphicTestType æä¸¾å¼
// æµè¯å½æ°å: æµè¯ç¨ä¾ç彿°å
æµè¯ç±»å (RSGraphicTestType)
enum RSGraphicTestType {
FRAMEWORK_TEST, // æ¡æ¶æµè¯
ANIMATION_TEST, // å¨ç»æµè¯
CONTENT_DISPLAY_TEST, // å
容æ¾ç¤ºæµè¯
SCREEN_MANAGER_TEST, // å±å¹ç®¡çæµè¯
HARDWARE_PRESENT_TEST, // 硬件åç°æµè¯
DRAWING_TEST, // ç»å¶æµè¯
LTPO_TEST, // LTPOæµè¯
TEXT_TEST, // ææ¬æµè¯
PIXMAP_TEST, // PixelMapæµè¯
SYMBOL_TEST, // ç¬¦å·æµè¯
EFFECT_TEST, // æææµè¯
HYBRID_RENDER_TEST, // æ··åæ¸²ææµè¯
GPU_COMPOSER_TEST, // GPUåææµè¯
};
TestDefInfo ç»æ
struct TestDefInfo {
std::string testCaseName; // æµè¯ç±»å
std::string testName; // æµè¯å½æ°å
RSGraphicTestType testType; // æµè¯ç±»å
RSGraphicTestMode testMode; // æµè¯æ¨¡å¼
std::string filePath; // æºæä»¶è·¯å¾
bool isMultiple; // æ¯å¦å¤æµè¯æ¨¡å¼
uint8_t testId; // æµè¯ID (夿µè¯æ¨¡å¼)
};
æµè¯æ³¨åæµç¨
// 1. å®è°ç¨æ¶æ³¨åæµè¯ä¿¡æ¯
TestDefManager::Instance().Regist(name, type, mode, file, isMultiple)
// 2. SetUp() 䏿£æ¥æ¯å¦è¿è¡å½åæµè¯
ShouldRunCurrentTest() {
auto extInfo = TestDefManager::GetTestInfo(caseName, testName);
if (filterTestTypes.count(extInfo->testType) == 0) return false;
if (runTestMode != ALL && extInfo->testMode != runTestMode) return false;
return true;
}
åæ°é 置说æ
å½ä»¤è¡åæ°
# è¿è¡ç¹å®ç±»åçæµè¯
./RSGraphicTest --testType=CONTENT_DISPLAY_TEST
# è¿è¡å¤ç§ç±»å
./RSGraphicTest --testType=CONTENT_DISPLAY_TEST --testType=ANIMATION_TEST
# è¿è¡ç¹å®æ¨¡å¼
./RSGraphicTest --testMode=AUTOMATIC # èªå¨æµè¯
./RSGraphicTest --testMode=MANUAL # æå¨æµè¯
./RSGraphicTest --testMode=DYNAMIC # 卿æµè¯
# 设置çå¾
æ¶é´
./RSGraphicTest --testCaseWaitTime=2000 # æµè¯ç¨ä¾çå¾
æ¶é´(ms)
./RSGraphicTest --normalWaitTime=100 # æ£å¸¸çå¾
æ¶é´(ms)
./RSGraphicTest --surfaceCaptureWaitTime=1500 # æªå¾çå¾
æ¶é´(ms)
./RSGraphicTest --manualTestWaitTime=3000 # æå¨æµè¯çå¾
æ¶é´(ms)
# 设置VSyncéç
./RSGraphicTest --vsyncRate=2
# è·³è¿æªå¾
./RSGraphicTest --skipCapture
# 使ç¨gtestè¿æ»¤å¨
./RSGraphicTest --gtest_filter=MyTest.*
./RSGraphicTest --gtest_filter=MyTest.MySpecificTest
RSParameterParse é 置项
class RSParameterParse {
std::string imageSavePath = "/data/local/graphic_test/";
int testCaseWaitTime = 1000; // æµè¯ç¨ä¾çå¾
æ¶é´(ms)
int normalWaitTime = 10; // æ£å¸¸çå¾
æ¶é´(ms)
int surfaceCaptureWaitTime = 1000; // æªå¾çå¾
æ¶é´(ms)
int manualTestWaitTime = 1500; // æå¨æµè¯çå¾
æ¶é´(ms)
std::unordered_set<RSGraphicTestType> filterTestTypes = {};
RSGraphicTestMode runTestMode = RSGraphicTestMode::ALL;
int32_t vsyncRate = 1;
bool skipCapture_ = false;
};
æµè¯è¿æ»¤é»è¾
// ShouldRunCurrentTest() ä¸çè¿æ»¤é»è¾
bool ShouldRunCurrentTest() {
auto extInfo = TestDefManager::GetTestInfo(caseName, testName);
// ç±»åè¿æ»¤
if (!filterTestTypes.empty() &&
filterTestTypes.count(extInfo->testType) == 0) {
return false;
}
// 模å¼è¿æ»¤
if (runTestMode != ALL && extInfo->testMode != runTestMode) {
return false;
}
return true;
}
æµè¯æ¨¡æ¿åº
åºç¡æµè¯æ¨¡æ¿
#include "rs_graphic_test.h"
using namespace testing;
using namespace testing::ext;
namespace OHOS::Rosen {
class MyFeatureTest : public RSGraphicTest {
public:
void BeforeEach() override
{
// 设置å±å¹å°ºå¯¸
SetScreenSize(1200, 2000);
// 设置Surfaceè¾¹ç
SetSurfaceBounds({0, 0, 1200, 2000});
}
};
/*
* @tc.name: BasicFeatureTest
* @tc.desc: æµè¯åºæ¬åè½
* @tc.type: FUNC
* @tc.require: issue12345
*/
GRAPHIC_TEST(MyFeatureTest, CONTENT_DISPLAY_TEST, BasicFeatureTest)
{
// 1. å建èç¹
auto canvasNode = RSCanvasNode::Create();
// 2. è®¾ç½®å±æ§
canvasNode->SetBounds({100, 100, 500, 500});
canvasNode->SetFrame({100, 100, 500, 500});
canvasNode->SetBackgroundColor(0xFFFFFFFF);
// 3. æ·»å å°åºæ¯
GetRootNode()->AddChild(canvasNode);
// 4. 注åèç¹ (å¿
é¡»!)
RegisterNode(canvasNode);
// 5. å½å¶ç»å¶
auto drawing = canvasNode->BeginRecording(500, 500);
drawing->DrawRect({50, 50, 450, 450}, Drawing::Paint());
canvasNode->FinishRecording();
// 6. å·æ°äºå¡
RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
}
} // namespace OHOS::Rosen
ç½æ ¼å¸å±æ¨¡æ¿
/*
* @tc.name: GridLayoutTest
* @tc.desc: å¤é¡¹æµè¯ç½æ ¼å¸å±
* @tc.type: FUNC
*/
GRAPHIC_TEST(MyFeatureTest, CONTENT_DISPLAY_TEST, GridLayoutTest)
{
// æµè¯é¡¹é
ç½®
int32_t itemCount = 12;
int32_t nodeWidth = 200;
int32_t nodeHeight = 200;
int32_t gap = 50;
int32_t column = 4;
// çææµè¯é¢è²æ°ç»
uint32_t colors[] = {
0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFFFFFF00,
0xFFFF00FF, 0xFF00FFFF, 0xFFFF8000, 0xFF808080,
0xFF800000, 0xFF008000, 0xFF000080, 0xFF808000
};
for (int32_t i = 0; i < itemCount; i++) {
auto node = RSCanvasNode::Create();
// 计ç®ä½ç½®
int32_t row = i / column;
int32_t col = i % column;
int32_t x = gap + (nodeWidth + gap) * col;
int32_t y = gap + (nodeHeight + gap) * row;
// è®¾ç½®å±æ§
node->SetBounds({x, y, nodeWidth, nodeHeight});
node->SetFrame({x, y, nodeWidth, nodeHeight});
node->SetBackgroundColor(colors[i]);
GetRootNode()->AddChild(node);
RegisterNode(node);
}
RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
}
å¨ç»æµè¯æ¨¡æ¿
æ¹å¼1: RSNode::Animate (æ¨è – 忬¡å¨ç»)
/*
* @tc.name: AnimationClosureTest
* @tc.desc: æµè¯å¨ç»éå
ææ
* @tc.type: FUNC
*/
GRAPHIC_TEST(MyFeatureTest, ANIMATION_TEST, AnimationClosureTest)
{
auto node = RSCanvasNode::Create();
node->SetBounds({100, 100, 400, 400});
node->SetFrame({100, 100, 400, 400});
node->SetBackgroundColor(0xFF0000FF);
GetRootNode()->AddChild(node);
RegisterNode(node);
// 使ç¨RSNode::Animateå建å¨ç»éå
RSAnimationTimingProtocol protocol;
protocol.SetDuration(300); // 300ms - æµè¯ç¨å»ºè®®å¼ï¼é¿å
è¿é¿
protocol.SetRepeat(1); // æ§è¡1次
auto timingCurve = RSAnimationTimingCurve::EASE_IN_OUT;
RSNode::Animate(protocol, timingCurve,
[&]() {
// å¨ç»éå
: ææå±æ§ä¿®æ¹ä¼è¢«å¨ç»å
node->SetTranslate({50, 50}); // å°å¹
度平移
node->SetScale(1.2f); // é度缩æ¾
node->SetAlpha(0.8f); // éæåº¦
node->SetRotation(45.0f); // æè½¬è§åº¦
},
[]() {
// å¨ç»å®æåè° (å¯é)
std::cout << "Animation finished" << std::endl;
}
);
RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
}
æ¹å¼2: OpenImplicitAnimation/CloseImplicitAnimation
/*
* @tc.name: ImplicitAnimationTest
* @tc.desc: æµè¯æ¾å¼å¨ç»éå
* @tc.type: FUNC
*/
GRAPHIC_TEST(MyFeatureTest, ANIMATION_TEST, ImplicitAnimationTest)
{
auto node = RSCanvasNode::Create();
node->SetBounds({100, 100, 400, 400});
node->SetFrame({100, 100, 400, 400});
node->SetBackgroundColor(0xFF00FF00);
GetRootNode()->AddChild(node);
RegisterNode(node);
// æå¼å¨ç»éå
RSAnimationTimingProtocol protocol;
protocol.SetDuration(250); // 250ms
protocol.SetRepeat(1);
RSNode::OpenImplicitAnimation(protocol, RSAnimationTimingCurve::EASE_IN);
// éå
å
çææå±æ§ä¿®æ¹é½ä¼è¢«å¨ç»å
node->SetTranslate({30, 30});
node->SetRotation(90.0f);
// å
³éå¨ç»éå
ï¼è¿åå建çå¨ç»å表
auto animations = RSNode::CloseImplicitAnimation();
RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
}
å¤ä¸ªå¨ç»èç¹æµè¯æ¨¡æ¿
/*
* @tc.name: MultipleAnimationTest
* @tc.desc: æµè¯å¤ä¸ªèç¹å¨ç»
* @tc.type: FUNC
*/
GRAPHIC_TEST(MyFeatureTest, ANIMATION_TEST, MultipleAnimationTest)
{
const int nodeCount = 4;
const int nodeSize = 150;
const int gap = 50;
for (int i = 0; i < nodeCount; i++) {
auto node = RSCanvasNode::Create();
int x = 100 + (nodeSize + gap) * i;
int y = 200;
node->SetBounds({x, y, nodeSize, nodeSize});
node->SetFrame({x, y, nodeSize, nodeSize});
node->SetBackgroundColor(0xFF0000FF + (i * 0x00110000));
GetRootNode()->AddChild(node);
RegisterNode(node);
// æ¯ä¸ªèç¹ç¬ç«çå¨ç»
RSAnimationTimingProtocol protocol;
protocol.SetDuration(200 + i * 50); // 200ms, 250ms, 300ms, 350ms
protocol.SetRepeat(1);
RSNode::Animate(protocol, RSAnimationTimingCurve::EASE_OUT,
[node, i]() {
node->SetTranslate({0.0f, -50.0f - i * 10.0f}); // ä¸ååç§»é
node->SetScale(1.1f + i * 0.05f);
}
);
}
RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
}
PixelMap æµè¯æ¨¡æ¿
/*
* @tc.name: PixelMapDisplayTest
* @tc.desc: æµè¯PixelMapæ¾ç¤º
* @tc.type: FUNC
*/
GRAPHIC_TEST(MyFeatureTest, PIXMAP_TEST, PixelMapDisplayTest)
{
// å è½½å¾ç
auto pixelMap = DecodePixelMap(
"/data/local/tmp/test.jpg",
Media::AllocatorType::SHARE_MEM_ALLOC
);
if (!pixelMap) {
std::cout << "Failed to load pixelmap" << std::endl;
return;
}
// 使ç¨å¾çèç¹
auto node = SetUpNodeBgImage("/data/local/tmp/test.jpg", {100, 100, 500, 500});
GetRootNode()->AddChild(node);
RegisterNode(node);
// æå¨Canvasä¸ç»å¶
auto canvasNode = RSCanvasNode::Create();
canvasNode->SetBounds({100, 100, 500, 500});
canvasNode->SetFrame({100, 100, 500, 500});
GetRootNode()->AddChild(canvasNode);
RegisterNode(canvasNode);
auto drawing = canvasNode->BeginRecording(500, 500);
auto extendDrawing = static_cast<ExtendRecordingCanvas*>(drawing);
Drawing::SamplingOptions sampling;
extendDrawing->DrawPixelMapWithParm(pixelMap, {}, sampling);
canvasNode->FinishRecording();
RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
}
忢æµè¯æ¨¡æ¿
/*
* @tc.name: TransformTest
* @tc.desc: æµè¯åæ¢æä½
* @tc.type: FUNC
*/
GRAPHIC_TEST(MyFeatureTest, DRAWING_TEST, TransformTest)
{
float scales[] = {0.5f, 1.0f, 1.5f, 2.0f};
float angles[] = {0.0f, 45.0f, 90.0f, 135.0f};
int32_t scaleCount = sizeof(scales) / sizeof(scales[0]);
int32_t angleCount = sizeof(angles) / sizeof(angles[0]);
int32_t nodeSize = 200;
int32_t gap = 50;
for (int32_t i = 0; i < scaleCount; i++) {
for (int32_t j = 0; j < angleCount; j++) {
auto node = RSCanvasNode::Create();
int32_t x = gap + (nodeSize + gap) * j;
int32_t y = gap + (nodeSize + gap) * i;
node->SetBounds({x, y, nodeSize, nodeSize});
node->SetFrame({x, y, nodeSize, nodeSize});
node->SetBackgroundColor(0xFFFFFFFF);
GetRootNode()->AddChild(node);
RegisterNode(node);
auto drawing = node->BeginRecording(nodeSize, nodeSize);
// åºç¨åæ¢
drawing->Translate(nodeSize / 2, nodeSize / 2);
drawing->Rotate(angles[j]);
drawing->Scale(scales[i], scales[i]);
drawing->Translate(-nodeSize / 2, -nodeSize / 2);
// ç»å¶ç©å½¢
Drawing::Paint paint;
paintSetColor(paint, 0xFFFF0000);
drawing->DrawRect({50, 50, 150, 150}, paint);
node->FinishRecording();
}
}
RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
}
è¾¹ç弿µè¯æ¨¡æ¿
/*
* @tc.name: BoundaryValueTest
* @tc.desc: æµè¯è¾¹çå¼
* @tc.type: FUNC
*/
GRAPHIC_TEST(MyFeatureTest, CONTENT_DISPLAY_TEST, BoundaryValueTest)
{
// æµè¯è¾¹çå¼ï¼è´æ°ãé¶ã大æ°å¼
float values[] = {
-100.0f, -10.0f, -1.0f, 0.0f, // è´æ°åé¶
0.1f, 1.0f, 10.0f, 100.0f, // æ£å¸¸å¼
1000.0f, 10000.0f // 大æ°å¼
};
int32_t count = sizeof(values) / sizeof(values[0]);
int32_t nodeWidth = 300;
int32_t nodeHeight = 100;
int32_t gap = 30;
for (int32_t i = 0; i < count; i++) {
auto node = RSCanvasNode::Create();
int32_t y = gap + (nodeHeight + gap) * i;
node->SetBounds({50, y, nodeWidth, nodeHeight});
node->SetFrame({50, y, nodeWidth, nodeHeight});
node->SetBackgroundColor(0xFFFFFFFF);
GetRootNode()->AddChild(node);
RegisterNode(node);
auto drawing = node->BeginRecording(nodeWidth, nodeHeight);
// 使ç¨è¾¹çå¼è¿è¡æµè¯
char text[64];
snprintf(text, sizeof(text), "Value: %.1f", values[i]);
drawing->DrawTextBlob(..., text); // ç»å¶ææ¬
// æç»å¶å
¶ä»å¾å½¢è¡¨ç¤º
node->FinishRecording();
}
RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
}
æå¨æªå¾æµè¯æ¨¡æ¿
class MyManualTest : public RSGraphicTest {
public:
void BeforeEach() override
{
SetScreenSize(1200, 2000);
SetSurfaceBounds({0, 0, 1200, 2000});
}
void TestCaseCapture()
{
auto pixelMap = DisplayManager::GetInstance().GetScreenshot(
DisplayManager::GetInstance().GetDefaultDisplayId()
);
if (pixelMap) {
const auto* testInfo = ::testing::UnitTest::GetInstance()->current_test_info();
std::string fileName = "/data/local/graphic_test/my_test/";
fileName += std::string(testInfo->test_case_name()) + "_" +
std::string(testInfo->name()) + ".png";
// å建ç®å½
namespace fs = std::filesystem;
fs::create_directories(fileName.substr(0, fileName.find_last_of('/')));
if (!WriteToPngWithPixelMap(fileName, *pixelMap)) {
std::cout << "[FAILED] " << fileName << std::endl;
} else {
std::cout << "png write to " << fileName << std::endl;
}
}
}
};
/*
* @tc.name: ManualCaptureTest
* @tc.desc: æå¨æ§å¶æªå¾æ¶æº
* @tc.type: FUNC
*/
GRAPHIC_N_TEST(MyManualTest, CONTENT_DISPLAY_TEST, ManualCaptureTest)
{
auto node = RSCanvasNode::Create();
node->SetBounds({100, 100, 500, 500});
node->SetFrame({100, 100, 500, 500});
node->SetBackgroundColor(0xFF0000FF);
GetRootNode()->AddChild(node);
RegisterNode(node);
auto drawing = node->BeginRecording(500, 500);
drawing->DrawRect({100, 100, 400, 400}, Drawing::Paint());
node->FinishRecording();
RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
// çå¾
渲æå®æ
usleep(1000000); // 1ç§
// æå¨æªå¾
TestCaseCapture();
}
æä½³å®è·µ
å¿ é¡»éµå®çè§å
-
å§ç»è°ç¨ RegisterNode()
GetRootNode()->AddChild(node); RegisterNode(node); // å¿ é¡»ï¼ -
å·æ°äºå¡
RSTransactionProxy::GetInstance()->FlushImplicitTransaction(); -
ä½¿ç¨ BeforeEach 设置ç¯å¢
void BeforeEach() override { SetScreenSize(1200, 2000); SetSurfaceBounds({0, 0, 1200, 2000}); }
èç¹å±æ§è®¾ç½®é¡ºåº
// æ¨è顺åº
auto node = RSCanvasNode::Create();
node->SetBounds({x, y, w, h}); // 1. å
设置边ç
node->SetFrame({x, y, w, h}); // 2. å设置帧
node->SetBackgroundColor(color); // 3. è®¾ç½®èæ¯
GetRootNode()->AddChild(node); // 4. æ·»å å°åºæ¯
RegisterNode(node); // 5. 注åèç¹
é¢è²æ ¼å¼
// ARGB æ ¼å¼: 0xAARRGGBB
uint32_t color = 0xFFFF0000; // ä¸éæçº¢è²
// 常ç¨é¢è²
0xFF000000 // é»è²
0xFFFFFFFF // ç½è²
0xFFFF0000 // 红è²
0xFF00FF00 // 绿è²
0xFF0000FF // èè²
ç½æ ¼å¸å±è®¡ç®
// 计ç®ç½æ ¼ä½ç½®
int32_t row = i / column;
int32_t col = i % column;
int32_t x = gap + (nodeWidth + gap) * col;
int32_t y = gap + (nodeHeight + gap) * row;
èµæºè·¯å¾
// å¾çè·¯å¾
std::string imagePath = "/data/local/tmp/test.jpg";
// æªå¾ä¿åè·¯å¾
std::string savePath = "/data/local/graphic_test/<åç±»>/<æµè¯ç±»>_<æµè¯å>.png";
常è§é误
| é误 | åå | è§£å³æ¹æ¡ |
|---|---|---|
| èç¹ä¸æ¾ç¤º | æªè°ç¨ RegisterNode() | æ·»å RegisterNode(node) |
| æªå¾ç©ºç½ | æªå·æ°äºå¡ | æ·»å FlushImplicitTransaction() |
| èç¹ä½ç½®é误 | Bounds/Frame 设置ä¸ä¸è´ | ç¡®ä¿ Bounds å Frame ä¸è´ |
| å åæ³æ¼ | nodes_ æªæ¸ ç | æ¡æ¶èªå¨æ¸ çï¼æ£æ¥æ¯å¦æé¢å¤å¼ç¨ |
| å¨ç»æªæ§è¡ | æªè°ç¨StartUIAnimation | æ¡æ¶å¨TearDownèªå¨è°ç¨ï¼ææå¨è°ç¨ |
| å¨ç»æµè¯è¶ æ¶ | duration/repeat设置è¿å¤§ | 使ç¨200-500msï¼repeat=1 |
å¨ç»æµè¯æä½³å®è·µ
// 1. 使ç¨åççå¨ç»æ¶é¿ (200-500ms)
RSAnimationTimingProtocol protocol;
protocol.SetDuration(300); // â
æ¨è: 300ms
protocol.SetDuration(5000); // â é¿å
: è¿é¿å¯¼è´æµè¯è¶
æ¶
// 2. é¿å
æ é循ç¯
protocol.SetRepeat(1); // â
æ¨è: æ§è¡1次
protocol.SetRepeat(0); // â é¿å
: æ é循ç¯
// 3. 使ç¨å°å¹
度åå
node->SetTranslate({50, 50}); // â
æ¨è: å°å¹
度
node->SetTranslate({1000, 1000}); // â é¿å
: è¿å¤§åç§»
// 4. é¦éRSNode::Animateéå
RSNode::Animate(protocol, curve, [&]() {
node->SetTranslate({30, 30});
}); // â
æ¨è: ç®æ´æ¸
æ°
// vs æ¾å¼éå
(éè¦æå¨å¹é
Open/Close)
RSNode::OpenImplicitAnimation(protocol, curve);
node->SetTranslate({30, 30});
RSNode::CloseImplicitAnimation(); // â ï¸ å¯é: æ´çµæ´»ä½å®¹æéæ¼
è°è¯æå·§
// 1. æ¥çèç¹æ
GetRootNode()->DumpTree();
// 2. è¾åºæ¥å¿
LOGI("Test message: %s", "debug info");
std::cout << "Debug: " << value << std::endl;
// 3. åç¬è¿è¡æµè¯
./RSGraphicTest --gtest_filter=MyTest.MySpecificTest
// 4. è·³è¿æªå¾å¿«éè°è¯
./RSGraphicTest --skipCapture
æ§è½å»ºè®®
- å¤ç¨ PixelMapï¼é¿å éå¤è§£ç åä¸å¾ç
- æ§å¶èç¹æ°éï¼åæµè¯å»ºè®®ä¸è¶ è¿ 100 个èç¹
- åç设置çå¾ æ¶é´ï¼æ ¹æ®æ¸²æå¤æåº¦è°æ´ waitTime
- 使ç¨ç½æ ¼å¸å±ï¼å¤ä¸ªæµè¯é¡¹æ¶ä½¿ç¨ GRAPHIC_TESTS
åè示ä¾
ç°ææµè¯ç¨ä¾ä½ç½®
graphic_test/test/open_capability/pixmap/pixelmap_display_test.cpp– PixelMap æµè¯graphic_test/test/rs_perform_feature/dirty_region/boundary_test.cpp– è¾¹çæµè¯graphic_test/test/rs_perform_feature/dirty_region/merge_dirty_rect_test.cpp– èåºååå¹¶æµè¯graphic_test/test/rs_perform_feature/gpu_composer/gpu_composer_test.cpp– GPU åææµè¯graphic_test/test/drawing_engine/drawing/demo.cpp– ç»å¶å¼æç¤ºä¾
æµè¯æ¡æ¶APIåè
RSGraphicTest åºç±»
å±å¹åSurface管ç
// è·åå±å¹å°ºå¯¸
Vector2f GetScreenSize() const;
// è¿å: {width, height}
// 设置å±å¹å°ºå¯¸
void SetScreenSize(float width, float height);
// 设置æµè¯Surfaceè¾¹ç
void SetSurfaceBounds(const Vector4f& bounds);
// bounds: {left, top, right, bottom} æ {x, y, width, height}
// 设置å±å¹Surfaceè¾¹ç (夿µè¯æ¨¡å¼)
void SetScreenSurfaceBounds(const Vector4f& bounds);
// 设置Surfaceèæ¯è²
void SetSurfaceColor(const RSColor& color);
// color: 0xAARRGGBB æ ¼å¼
èç¹ç®¡ç
// è·åæ ¹èç¹
std::shared_ptr<RSGraphicRootNode> GetRootNode() const;
// 注åèç¹ (å¿
é¡»è°ç¨)
void RegisterNode(std::shared_ptr<RSNode> node);
// ä½ç¨: ä¿æèç¹å¼ç¨ï¼é²æ¢è¢«æåéæ¾
// 仿件å 载渲æèç¹æ
void AddFileRenderNodeTreeToNode(std::shared_ptr<RSNode> node,
const std::string& filePath);
å¨ç»å忥
// å¼å§æ§è¡UIå¨ç» (å¨TearDownä¸èªå¨è°ç¨)
void StartUIAnimation();
// çå¾
æå®æ¯«ç§æ°
void WaitTimeout(int ms);
å¨ç»éå API (RSNodeéææ¹æ³):
// æ¹å¼1: RSNode::Animate - 忬¡å¨ç»éå
static std::vector<std::shared_ptr<RSAnimation>> Animate(
const RSAnimationTimingProtocol& timingProtocol, // æ¶åºåè®®
const RSAnimationTimingCurve& timingCurve, // ç¼å¨æ²çº¿
const PropertyCallback& callback, // 屿§ä¿®æ¹éå
const std::function<void()>& finishCallback = nullptr, // 宿åè°
const std::function<void()>& repeatCallback = nullptr // éå¤åè°
);
// æ¹å¼2: OpenImplicitAnimation/CloseImplicitAnimation - æ¾å¼å¨ç»éå
static void OpenImplicitAnimation(
const RSAnimationTimingProtocol& timingProtocol,
const RSAnimationTimingCurve& timingCurve,
const std::function<void()>& finishCallback = nullptr
);
static std::vector<std::shared_ptr<RSAnimation>> CloseImplicitAnimation();
å¨ç»åæ°å»ºè®® (é¿å æ§è¡æ¶é´è¿é¿):
| åæ° | å»ºè®®å¼ | 说æ |
|---|---|---|
| duration | 200-500ms | æµè¯å¨ç»ä¸å®è¿é¿ |
| repeat | 1次æ0次 | é¿å æ éå¾ªç¯ |
| delay | 0-100ms | åå°çå¾ æ¶é´ |
| translate/scale | å°å¹ 度åå | é¿å è¿å¤§çåæ åç§» |
RSAnimationTimingProtocol:
RSAnimationTimingProtocol protocol;
protocol.SetDuration(500); // æç»æ¶é´(毫ç§)
protocol.SetRepeat(1); // é夿¬¡æ°(0=æ é, 1=䏿¬¡)
protocol.SetDelay(0); // å»¶è¿æ¶é´
protocol.SetSpeed(1.0f); // ææ¾é度
protocol.SetDirection(Direction::NORMAL); // ææ¾æ¹å
RSAnimationTimingCurve é¢è®¾:
RSAnimationTimingCurve::EASE // ç¼å¨
RSAnimationTimingCurve::EASE_IN // ç¼å
¥
RSAnimationTimingCurve::EASE_OUT // ç¼åº
RSAnimationTimingCurve::EASE_IN_OUT // ç¼å
¥ç¼åº
RSAnimationTimingCurve::LINEAR // 线æ§
RSAnimationTimingCurve::SPRING // 弹簧
çå½å¨æé©å
// ç¨æ·éå: æ¯ä¸ªæµè¯ç¨ä¾æ§è¡å
virtual void BeforeEach() {}
// ç¨æ·éå: æ¯ä¸ªæµè¯ç¨ä¾æ§è¡å
virtual void AfterEach() {}
åæ¾åè½
// åå¤åæ¾
void PlaybackRecover(const std::string& filePath, float pauseTimeStamp);
// filePath: å½å¶æä»¶è·¯å¾
// pauseTimeStamp: æåæ¶é´æ³(ç§)
// 忢忾
void PlaybackStop();
RSGraphicTestDirector åä¾
// è·ååä¾
static RSGraphicTestDirector& Instance();
// è·åæ ¹èç¹
std::shared_ptr<RSGraphicRootNode> GetRootNode() const;
// è·åå±å¹å°ºå¯¸
Vector2f GetScreenSize() const;
// 设置å±å¹å°ºå¯¸
void SetScreenSize(float width, float height);
// 设置Surfaceè¾¹ç
void SetSurfaceBounds(const Vector4f& bounds);
// 设置å±å¹Surfaceè¾¹ç
void SetScreenSurfaceBounds(const Vector4f& bounds);
// 设置Surfaceé¢è²
void SetSurfaceColor(const RSColor& color);
// å·æ°æ¶æ¯
void FlushMessage();
// å·æ°å¹¶çå¾
bool FlushMessageAndWait(int timeoutMs);
// æªå¾
std::shared_ptr<Media::PixelMap> TakeScreenCaptureAndWait(int ms, bool isScreenShot = false);
// 设置/è·ååæµè¯æ¨¡å¼
void SetSingleTest(bool isSingleTest);
bool IsSingleTest();
// 设置/è·å卿æµè¯æ¨¡å¼
void SetDynamicTest(bool isDynamicTest);
bool IsDynamicTest();
// å¯å¨å¨ç»
void StartRunUIAnimation();
// æ£æ¥æ¯å¦æè¿è¡ä¸çå¨ç»
bool HasUIRunningAnimation();
// åéProfilerå½ä»¤
void SendProfilerCommand(const std::string command, int outTime = 0);
å¾çè¾ å©å½æ° (rs_graphic_test_img.h)
// è§£ç PixelMap
std::shared_ptr<Media::PixelMap> DecodePixelMap(
const std::string& pathName,
const Media::AllocatorType& allocatorType,
const Media::PixelFormat& dstFormat = Media::PixelFormat::RGBA_8888
);
// pathName: å¾çæä»¶è·¯å¾
// allocatorType: éå¸¸ä½¿ç¨ Media::AllocatorType::SHARE_MEM_ALLOC
// dstFormat: ç®æ åç´ æ ¼å¼
// 设置èç¹èæ¯å¾ç (è·¯å¾)
std::shared_ptr<RSCanvasNode> SetUpNodeBgImage(
const std::string& pathName,
const Vector4f bounds
);
// 设置èç¹èæ¯å¾ç (æ°æ®)
std::shared_ptr<RSCanvasNode> SetUpNodeBgImage(
const uint8_t* data,
uint32_t size,
const Vector4f bounds
);
å·¥å ·å½æ° (rs_graphic_test_utils.h)
// ä¿åPixelMap为PNG
bool WriteToPngWithPixelMap(const std::string& fileName,
Media::PixelMap& pixelMap);
// çå¾
æå®æ¯«ç§
void WaitTimeout(int ms);
Drawing API åè
è·åRecording Canvas
auto drawing = canvasNode->BeginRecording(width, height);
// ... æ§è¡ç»å¶æä½ ...
canvasNode->FinishRecording();
å ä½å¾å½¢ç»å¶
// ç¹
drawing->DrawPoint(point);
drawing->DrawPoints(PointMode::POINTS, count, pts);
// PointMode: POINTS, LINES, POLYGON
// 线
drawing->DrawLine(startPt, endPt);
// ç©å½¢
drawing->DrawRect(rect);
// åè§ç©å½¢
drawing->DrawRoundRect(roundRect);
drawing->DrawNestedRoundRect(outer, inner);
// å¼§å½¢
drawing->DrawArc(oval, startAngle, sweepAngle);
// 饼å¾
drawing->DrawPie(oval, startAngle, sweepAngle);
// æ¤å
drawing->DrawOval(oval);
// åå½¢
drawing->DrawCircle(center, radius);
// è·¯å¾
drawing->DrawPath(path);
// åºå
drawing->DrawRegion(region);
// ç½æ ¼é¢ç
drawing->DrawPatch(cubics[12], colors[4], texCoords[4], mode);
// é¡¶ç¹ç½æ ¼
drawing->DrawVertices(vertices, mode);
å¾çç»å¶
// ä½å¾
drawing->DrawBitmap(bitmap, x, y);
// å¾ç (ç®åä½ç½®)
drawing->DrawImage(image, x, y, sampling);
// å¾ç (æº-ç®æ ç©å½¢)
drawing->DrawImageRect(image, src, dst, sampling, constraint);
drawing->DrawImageRect(image, dst, sampling);
// ä¹å®«æ ¼
drawing->DrawImageNine(image, center, dst, filterMode, brush);
drawing->DrawImageLattice(image, lattice, dst, filterMode);
// å¾é
drawing->DrawAtlas(atlas, xform[], tex[], colors[], count, mode, sampling);
PixelMap ç»å¶ (ExtendRecordingCanvas)
auto extendDrawing = static_cast<ExtendRecordingCanvas*>(drawing);
// 另忰ç»å¶
extendDrawing->DrawPixelMapWithParm(pixelMap, rsImageInfo, sampling);
// ç©å½¢åºå
extendDrawing->DrawPixelMapRect(pixelMap, src, dst, sampling, constraint);
// ä¹å®«æ ¼
extendDrawing->DrawPixelMapNine(pixelMap, center, dst, filterMode);
extendDrawing->DrawPixelMapLattice(pixelMap, lattice, dst, filterMode);
// 带Brushçä¹å®«æ ¼
extendDrawing->DrawImageNineWithPixelMap(pixelMap, center, dst, filter, brush);
// SurfaceBuffer
#ifdef ROSEN_OHOS
extendDrawing->DrawSurfaceBuffer(surfaceBufferInfo);
#endif
é¢è²åææ¬
// çº¯è² (å¸¦æ··åæ¨¡å¼)
drawing->DrawColor(color, BlendMode::SRC_OVER);
// èæ¯
drawing->DrawBackground(brush);
// ææ¬å
drawing->DrawTextBlob(blob, x, y);
// 符å·
drawing->DrawSymbol(symbolData, locate);
// Picture
drawing->DrawPicture(picture);
è£åªæä½
// ç©å½¢è£åª
drawing->ClipRect(rect, ClipOp::INTERSECT, doAntiAlias);
// ClipOp: DIFFERENCE, INTERSECT
// åè§ç©å½¢è£åª
drawing->ClipRoundRect(roundRect, ClipOp::INTERSECT, doAntiAlias);
// è·¯å¾è£åª
drawing->ClipPath(path, ClipOp::INTERSECT, doAntiAlias);
// åºåè£åª
drawing->ClipRegion(region, ClipOp::INTERSECT);
// èªéåºåè§è£åª
drawing->ClipAdaptiveRoundRect(radius[4]);
忢æä½
// 设置ç©éµ
drawing->SetMatrix(matrix);
// éç½®ç©éµ
drawing->ResetMatrix();
// è¿æ¥ç©éµ
drawing->ConcatMatrix(matrix);
// 平移
drawing->Translate(dx, dy);
// 缩æ¾
drawing->Scale(sx, sy);
// æè½¬ (ç»æå®ä¸å¿)
drawing->Rotate(degrees, cx, cy);
// éå
drawing->Shear(sx, sy);
ç¶æç®¡ç
// ä¿åç¶æ
uint32_t saveCount = drawing->Save();
// ä¿åå¾å± (ç¦»å±æ¸²æ)
drawing->SaveLayer(saveLayerOps);
// æ¢å¤ç¶æ
drawing->Restore();
// è·åä¿å屿°
uint32_t count = drawing->GetSaveCount();
// ä¸¢å¼æææªæ¢å¤çä¿å
drawing->Discard();
å ¶ä»æä½
// æ¸
空
drawing->Clear();
drawing->Clear(color);
// å·æ°
drawing->Flush();
// èªå®ä¹ææ¬ç±»å
drawing->SetIsCustomTextType(true);
bool isCustom = drawing->IsCustomTextType();
// èªå®ä¹åä½
drawing->SetIsCustomTypeface(true);
bool isCustomTypeface = drawing->IsCustomTypeface();
// å½å¶å½ä»¤æ¨¡å¼
drawing->SetIsRecordCmd(true);
bool isRecordCmd = drawing->IsRecordCmd();
// éç½®æ··åæ¸²æå°ºå¯¸
drawing->ResetHybridRenderSize(width, height);
èªå®ä¹ç»å¶å½æ°
using DrawFunc = std::function<void(Drawing::Canvas* canvas, const Drawing::Rect* rect)>;
extendDrawing->DrawDrawFunc([](Drawing::Canvas* canvas, const Drawing::Rect* rect) {
// å»¶è¿ç»å¶
canvas->DrawRect(/* ... */);
});
BUILD.gn é 置模æ¿
import("//build/ohos.gni")
import("//foundation/graphic/graphic_2d/graphic_config.gni")
ohos_unittest("my_feature_test") {
module_out_name = "my_feature_test"
sources = [
"my_test.cpp",
]
include_dirs = [
"//foundation/graphic/graphic_2d/rosen/test",
"//foundation/graphic/graphic_2d/rosen/include",
"//foundation/graphic/graphic_2d/graphic_test/graphic_test_framework/include",
]
deps = [
"//foundation/graphic/graphic_2d/rosen:librosen",
"//foundation/graphic/graphic_2d/graphic_test/graphic_test_framework:libgraphic_test_framework",
]
external_deps = [
"hilog_native:libhilog",
"image_framework:image_native",
]
part_name = "graphic_2d"
subsystem_name = "graphic"
}
éå½
常ç¨å¤´æä»¶
#include "rs_graphic_test.h" // æµè¯åºç±»
#include "rs_graphic_test_img.h" // å¾çè¾
å©
#include "rs_graphic_test_utils.h" // å·¥å
·å½æ°
#include "ui/rs_canvas_node.h" // Canvasèç¹
#include "ui/rs_surface_node.h" // Surfaceèç¹
#include "transaction/rs_interfaces.h" // äºå¡æ¥å£
#include "display_manager.h" // æ¾ç¤ºç®¡çå¨
#include "pixel_map.h" // PixelMap
#include "image_source.h" // å¾çæº
常ç¨ç±»å
using Vector2f = OHOS::Rosen::Vector2f; // {x, y}
using Vector4f = OHOS::Rosen::Vector4f; // {left, top, right, bottom}
using RSColor = OHOS::Rosen::RSColor; // uint32_t é¢è²
æµè¯æ³¨éæ ¼å¼
/*
* @tc.name: TestName
* @tc.desc: æµè¯æè¿°
* @tc.type: FUNC | PERF | RELI
* @tc.require: issueç¼å· æ ARç¼å·
*/