
제출 브랜치
https://github.com/Saususge/thorvg.example/tree/example/custom
과제 코드
/*
* Copyright (c) 2020 - 2026 ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "Example.h"
/************************************************************************/
/* ThorVG Drawing Contents */
/************************************************************************/
struct UserExample : tvgexam::Example
{
bool content(tvg::Canvas* canvas, uint32_t w, uint32_t h) override
{
//White background
auto bg = tvg::Shape::gen();
bg->appendRect(0, 0, w, h);
bg->fill(255, 255, 255);
canvas->add(bg);
auto scene = tvg::Scene::gen();
float cx = float(w) * 0.5f;
//Blade — tapered path, pointed tip
float y_tip = 40.0f;
float y_blade_base = 200.0f;
float blade_half_base = 12.0f;
auto blade = tvg::Shape::gen();
blade->moveTo(cx - blade_half_base, y_blade_base);
blade->lineTo(cx, y_tip);
blade->lineTo(cx + blade_half_base, y_blade_base);
blade->close();
blade->fill(220, 220, 230);
blade->strokeFill(120, 120, 130);
blade->strokeWidth(1.5f);
scene->add(blade);
//Blade edge highlight
auto edge = tvg::Shape::gen();
edge->moveTo(cx, y_tip);
edge->lineTo(cx + blade_half_base, y_blade_base);
edge->strokeFill(255, 255, 255);
edge->strokeWidth(1.0f);
scene->add(edge);
//Guard (crossguard)
auto guard = tvg::Shape::gen();
guard->appendRect(cx - 55, y_blade_base - 5, 110, 16, 4, 4);
guard->fill(139, 90, 43);
guard->strokeFill(80, 50, 20);
guard->strokeWidth(1.5f);
scene->add(guard);
//Grip (handle)
auto grip = tvg::Shape::gen();
grip->appendRect(cx - 8, y_blade_base + 15, 16, 100, 4, 4);
grip->fill(101, 67, 33);
grip->strokeFill(60, 30, 10);
grip->strokeWidth(1.5f);
scene->add(grip);
//Grip wrapping lines
for (int i = 0; i < 5; i++) {
auto wrap = tvg::Shape::gen();
float wy = y_blade_base + 25 + i * 18;
wrap->moveTo(cx - 10, wy);
wrap->lineTo(cx + 10, wy);
wrap->strokeFill(80, 50, 20);
wrap->strokeWidth(1.0f);
scene->add(wrap);
}
//Pommel
auto pommel = tvg::Shape::gen();
pommel->appendCircle(cx, y_blade_base + 125, 14, 14);
pommel->fill(180, 160, 50);
pommel->strokeFill(100, 80, 20);
pommel->strokeWidth(1.5f);
scene->add(pommel);
canvas->add(scene);
return true;
}
};
/************************************************************************/
/* Entry Point */
/************************************************************************/
int main(int argc, char **argv)
{
return tvgexam::main(new UserExample, argc, argv, false, 400, 600);
}
주요 구현 내용
- 일단 판타지 스타일의 검을 tutorial에 나와있는 shape drawing으로만 구현해보려 했습니다.
- 캔버스는 큰게 필요없을거같아 main에서 400x600으로 윈도우 크기를 override했습니다
- 각 도형에 맞게 path, move, appendRect, appendCircle등을 이용하여 물체를 만들었습니다.
- grip은 반복문을 이용해 일정거리에 그려서 깔끔하게 처리하도록 했습니다.
- Example 구조체가 윈도우 생성과 같은 반복 작업을 추상화해줘서, 도형 구성에만 집중할 수 있었습니다.
- 좌표는 가로 중심을 기준으로 잡고, 도형 크기를 조정해가며 배치했습니다.
- SVG나 Skia처럼 벡터 도형을 조립하는 스타일과 비슷해서, 다른 예제를 참고하기도 쉬웠습니다.
- 과제의 코드는 src/CustomExample.cpp에 위치해 있습니다.
댓글
Discussion 원문