본문 바로가기
Algorithm

2.2 Canvas DrawXX < 나중에 다시 정리 >

by SimonLee 2025. 5. 7.

ex) Canvas_drawRect

 

 

setStyle 종류  ( 도형을 어떻게 그릴것인지 결정 )

style 종류 의미 설명 시각적 예
kFill_Style 채우기 전용 도형 안쪽을 채움 ■ ●
kStroke_Style 선(테두리)만 그림 내부는 비우고 외곽선만 그림 □ ○
kStrokeAndFill_Style 채우고 선도 그림 안도 채우고 테두리도 그림 ◎ ◉

 

 

setStrokeJoin 종류 ( 코너를 어떻게 그릴것인지 결정 )

stroke join 종류 의미 설명 시각적 예
SkPaint::kMiter_Join 날카로운 모서리 (뾰족하게) 연결 기본값, 각도가 작을수록 길게 튀어나올 수 있음 ┏━, ⎾ ┓
SkPaint::kBevel_Join 모서리를 뚝 자른 형태로 연결 뾰족함 없이 평평하게 잘림 ◣, ↘
SkPaint::kRound_Join 모서리를 둥글게 연결 부드러운 느낌, 곡선 UI에 적합 ⤾, ⤿, ◎

 

 

void draw(SkCanvas* canvas) {
    SkPoint rectPts[] = { {64, 48}, {192, 160} };
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(20);
    paint.setStrokeJoin(SkPaint::kRound_Join);
    SkMatrix rotator;
    rotator.setRotate(30, 128, 128);
    for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
        paint.setColor(color);
        SkRect rect;
        rect.set(rectPts[0], rectPts[1]);
        canvas->drawRect(rect, paint);
        rotator.mapPoints(rectPts, 2);
    }
}

 


 

Canvas_drawRegion

 

void draw(SkCanvas* canvas) {
    SkRegion region;
    region.op({10, 10, 50, 50}, SkRegion::kUnion_Op);
    region.op({10, 50, 90, 90}, SkRegion::kUnion_Op);
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(20);
    paint.setStrokeJoin(SkPaint::kRound_Join);
    canvas->drawRegion(region, paint);
}

 

SkRegion::OP 설명 예시
kUnion_Op 기존 Region과 새 영역의 합집합 둘 중 하나라도 포함되면 포함
kIntersect_Op 겹치는 부분만 남김 둘 다 포함되는 영역만 유지
kDifference_Op 기존 Region에서 새 영역을 제거 기존 영역에서 겹친 부분 빼기
kXOR_Op 겹치지 않는 부분만 남김 A 또는 B에만 속한 영역
kReverseDifference_Op 새 영역에서 기존 Region을 제거 새 영역에서 겹친 부분 빼기
kReplace_Op 기존 Region을 새 영역으로 완전히 대체 이전 Region은 무시됨

 

region.op({...}, kUnion_OP)

- kUnion_OP로 설정이 되어 있어서 두 영역의 합집합 부분이 region으로 처리됨. ㄴ 자로 렌더링

- kIntersect_Op로 설정 하면, 겹치는 부분이 없기 때문에 아무것도 나오지 않는다.

 

 

 

paint.setStyle(SkPaint::KStroke_Style) 

- 내부를 채우지 않고 테두리만 렌더링

 

setStrokeJoin(SkPint::KRound_Join)

- 테두리 코너 영역 라운드 처리

 


Canvas_drawLine

void draw(SkCanvas* canvas) {
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setColor(0xFF9a67be);
    paint.setStrokeWidth(20);
    canvas->skew(1, 0);
    canvas->drawLine(32, 96, 32, 160, paint);
    canvas->skew(-2, 0);
    canvas->drawLine(288, 96, 288, 160, paint);
}

 

 

 

 


Canvas_drawPicture_4

void draw(SkCanvas* canvas) {
    SkPaint paint;
    SkPictureRecorder recorder;

    // 1. SkPictureRecorder로 50x50 영역의 캔버스에 그림을 "기록" 시작
    SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);

    // 2. 세 가지 색상으로 반복해서 사각형을 그리되, 매번 변형을 누적 적용함
    for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 }) {
        paint.setColor(color);  // 현재 색상 설정
        recordingCanvas->drawRect({10, 10, 30, 40}, paint);  // (10,10)-(30,40)에 사각형 그림
        recordingCanvas->translate(10, 10);  // 이후 명령에 대해 캔버스를 (10,10)만큼 이동시킴
        recordingCanvas->scale(1.0f, 2.0f);  // 이후 명령에 대해 Y축 방향으로 2배 스케일 적용
        // → transform은 누적되므로 두 번째, 세 번째 사각형은 위치와 크기가 달라짐
    }

    // 3. 기록을 종료하고 SkPicture 객체를 생성
    sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();

    // 4. SkPicture를 캔버스에 3번 재생하되, 각기 다른 alpha 값과 위치에서 그림
    SkMatrix matrix;
    matrix.reset();  // 초기 행렬은 항등 행렬 (변형 없음)

    for (auto alpha : { 70, 140, 210 }) {
        paint.setAlpha(alpha);  // 투명도 설정 (점점 더 불투명해짐)
        canvas->drawPicture(playback, &matrix, &paint);  // SkPicture 재생
        matrix.preTranslate(70, 70);  // 다음 반복에서 그림 위치를 (70,70)만큼 이동
    }
}

 

 

beginRecording(w, h)를 호출하면 그림을 기록할 수 있는 SkCanvas * 를 리턴 받고,

해당 캔버스로 그림을 기록!

finishRecordingAsPicture()를 통해 기록된 내용을 재생가능한 객체 SkPicture로 전달 받음.

 

translate -> scale 순서대로 호출하면, 역순으로 적용이 된다.

BLUE  경우 Y 좌표 2배를 곱하고, translate (10, 10) 

GREEN 경우 Y 좌표 4배( 2배 * 2배) , translate (10 * 2 , 10 * 2) 

색상 사각형의 크기 설명
RED (10, 10) ~ (30, 40) 기본 상태
BLUE (20, 30) ~ (40, 90) (10, 10) ~ (30, 40)  * 2 (y)
(10, 20) ~ (30, 80) + (10, 10)
(20, 30) ~ (40, 90)
GREEN (30, 60) ~ (50, 180) (10, 10) ~ (30, 40) *  4(y)
(10, 40) ~ (30, 160) + (20, 20)
(30, 60) ~ (50, 180)

 

세번째 초록색 사각형은 Picture의 50, 50에 잘려서 보이지 않는다.


 

Canvas_drawString

 

void draw(SkCanvas* canvas) {
    SkPaint paint;

    // 2. 기본 글꼴을 검색해서 SkFont 생성
    SkFont font = SkFont(fontMgr->matchFamilyStyle(nullptr, {}));

    // 3. 텍스트 출력
    canvas->drawString("a small hello", 20, 20, font, paint);
}

 

 

matchFamilyStyle 함수

- nullptr: 기본 글꼴 패밀리 사용 (예: sans-serif)
- {}: 기본 스타일 (보통 Regular)

파라메터 타입 설명
familyName const char* 글꼴 패밀리 이름 (예: "Arial", "Noto Sans")
nullptr이면 시스템 기본 글꼴 사용
style const SkFontStyle& 글꼴의 굵기(weight), 기울임(slant), 너비(width) 설정
예: SkFontStyle::Bold(), {700, 5, SkFontStyle::kItalic_Slant} 등

 

drawString

파라메터 타입 설명
text const char* 출력할 문자열 (UTF-8)
x, y SkScalar 출력 위치 (텍스트의 baseline 기준 좌표) 바닥선
font const SkFont& 사용할 글꼴 정보 (SkTypeface, size 포함)
paint const SkPaint& 색상, 안티앨리어싱 등 스타일 지정

Canvas_drawText

void draw(SkCanvas* canvas) {
    SkPaint paint;
    SkFont defaultFont = SkFont(fontMgr->matchFamilyStyle(nullptr, {}));
    float textSizes[] = { 12, 18, 24, 36 };
    for (auto size: textSizes ) {
        defaultFont.setSize(size);
        canvas->drawString("Aa", 10, 20, defaultFont, paint);
        canvas->translate(0, size * 2);
    }
    defaultFont = SkFont(fontMgr->matchFamilyStyle(nullptr, {}));
    float yPos = 20;
    for (auto size: textSizes ) {
        float scale = size / 12.f;
        canvas->resetMatrix();
        canvas->translate(100, 0);
        canvas->scale(scale, scale);
        canvas->drawString("Aa", 10 / scale, yPos / scale, defaultFont, paint);
        yPos += size * 2;
    }
}

 

텍스트 크기 x y
Aa 12 10 20
Aa 24 10 20 + 12×2 = 44
Aa 36 10 44 + 24×2 = 92

 

텍스트 크기 스케일 x(10 / s) y(yPos / s)
Aa 12 1.0 10 20
Aa 24 2.0 5 22
Aa 36 3.0 3.33 30.67

 

Canvas_drawVertices

 

내일 

void draw(SkCanvas* canvas) {
    SkPaint paint;
    SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
    SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
    auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
            std::size(points), points, nullptr, colors);
    canvas->drawVertices(vertices.get(), SkBlendMode::kDst, paint);
}
728x90

'Algorithm' 카테고리의 다른 글

BackTracking 3  (1) 2024.06.15
BackTracking 2  (1) 2024.06.15
BackTracking 1  (0) 2024.06.15
Dynamic Programing 4  (0) 2024.06.15
Dynamic Programing 3  (0) 2024.06.15