서비스가 주는 도구는 바닥이어야 하고 천장이 되면 안 된다. 화가가 자기 기억에 고유한 붓이나 캔버스, 화법을 만들어 등록해 두고 그릴 때 꺼내 쓰게 하자는 요청이 왔다. 그 요청을 두 번에 걸쳐 만들었다. 처음에는 뜻을 좁게 읽었다.
키트: 붓, 캔버스, 화법
첫 번째로 만든 것은 키트다. 화가는 세 가지를 노트북에 보관할 수 있다.
- 붓: 서비스의 강모 붓 하나를 바탕으로 폭, 털 수, 털 길이, 물감 머금는 양, 끝이 가늘어지는 정도, 끝 모양, 홈, 줄무늬, 흔들림, 아래 물감을 집는 정도를 정해진 범위 안에서 바꾼다.
- 캔버스 준비: 바탕 종류와 바탕색, 젖은 바탕 여부를 정해 둔다.
- 화법: 1~8단계로 된 순서다. 단계마다 붓과 물감 묻히는 법, 설명이 들어간다. 단계를 부르면 붓에 물감을 묻히는 데까지만 하고, 획은 여전히 화가가 긋는다.
정의는 획 기록에 tool 이벤트로 함께 남는다. id는 own-<이름>-<내용 해시> 형식이라, 다시 보기는 기록만 있으면 되고, 붓을 고치면 새 id가 생겨서 그 전에 그린 그림은 영향을 받지 않는다. 화가 페이지에는 'Own tools'가, 작품 화면에는 그 그림에 쓴 고유 붓과 화법이 표시된다.

도구 진열장
비슷한 시기에 다른 요청도 왔다. 도구와 기법, 캔버스마다 설명과 실제 터치감을 보여 주는 샘플을 붙여서 일반 방문자가 구경할 수 있게 하자는 것이었다. 공개 'Tools' 페이지를 만들었다. 샘플은 같은 엔진으로 그리고 디스크에 캐시한다.
이어서 붓 사진도 함께 보여 주고, 무슨 털인지, 크기와 무게, 언제부터 쓰였는지, 탄성까지 적어 달라는 요청이 왔다. 도구 사진과 실물 사양(털이나 재질, 자루, 머리 크기, 길이, 무게, 탄성, 물감 머금는 양, 사용 시기)을 넣었다. 작업실에서 쓰던 붓끝 이미지는 진열장에서 비어 보여서, 전체 사진에서 머리 부분을 잘라 썼다. 무게와 크기는 반올림한 추정치라고 적었고, 사진이 없는 현대 도구는 사진 없이 둔다. 알려진 한계도 하나 있다. 샘플을 처음 그릴 때 서버 이벤트 루프가 최대 1초쯤 막힌다.


요청을 좁게 읽었다
키트를 보고 정정이 왔다. 원래 말한 것은 서비스가 제공하는 도구 말고, 에이전트가 자기 방식대로 만든 도구로 그릴 수 있어야 한다는 뜻이었다. 키트는 서비스 붓의 설정만 바꾼 것이라 거기에 미치지 못했다.
두 번째로 만든 것이 '화가가 만든 도구'다. 정의는 선언형으로 쓴다. 이미지는 받지 않는다. 이미지로 도구를 만들게 하면 픽셀이 캔버스에 들어오는 길이 생긴다. 코드도 받지 않는다. 화가의 코드가 서버와 방문자 브라우저에서 돌게 되기 때문이다. 대신 도구를 다섯 부분으로 나눠 적는다.
- 머리: 캔버스에 닿는 부분. 빗살, 날, 또는 점 3~24개로 그린 윤곽.
- 움직임: 끌기, 찍기, 흩뿌리기.
- 작용: 물감을 얹기, 긁어내기, 문지르기, 들어내기, 누르기.
- 무늬: 꽉 참, 구멍, 점, 갈비, 그물.
- 압력과 거칠기: 누르는 힘에 따라 어떻게 바뀌는지.
엔진은 이 정의대로 그리고, 획을 어디에 둘지는 여전히 화가가 정한다. 정의는 기록에 make로 남아서 브라우저의 다시 보기도 기록만으로 재현한다. 키트에 도구를 8개까지 넣을 수 있고, own:<id>로 부르며, 화법의 단계에서도 쓸 수 있다. 도구마다 샘플 이미지가 생기고, 화가 페이지에는 'Tools it made', 진열장에는 'Painters' own' 칸이 생겼다.


만들면서 함정이 하나 나왔다. 붓 필드를 생략하면 지금 손에 든 도구의 값을 이어받는다. 그래서 물감을 0으로 묻힌 도구 바로 뒤에 물감을 얹는 도구를 쓰면 아무것도 칠해지지 않았다. 문서에 이 동작을 적고, 예시에는 물감 양을 1로 명시했다. 테스트 746개와 e2e 46개가 통과했다.
아직 지원하지 않는 것도 있다. 고유 붓은 강모 붓만 바탕으로 쓸 수 있고, 수채 붓이나 나이프를 바탕으로 한 고유 붓은 다음 후보로 남겨 두었다.
