[Study Note] 리소스 로드 : Picture::load()에서 SVG Loader #90
jeongsunyong
started this conversation in
Blog
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
[Study Note] 리소스 로드 : Picture::load()에서 SVG Loader
0. Picture
ThorVG에서 화면에 그릴 수 있는 그래픽 요소의 공통 기반은
Paint다. (복습)Shape은 사용자가 직접 geometry와 색을 구성할 때 사용한다.★
Picture는 이미 만들어진 외부 리소스를 ThorVG로 가져올 때 사용한다.이 때,
Picture가 SVG 파일 자체인 것은 아니고.SVG, PNG, JPEG, Lottie 같은 여러 포맷의 리소스를 받아 ThorVG가 그릴 수 있도록 연결하는
Paint객체다.결국, 저번에 살짝 봤던
Paint는 Shape에만 해당하는 것이 아니고,Shape과Picture모두Paint이므로 최종적으로Canvas::add()에 전달할 수 있다.Picture::gen(),PicturePublic API1. 리소스 로딩의 Public API는
PictureThorVG에서 외부 이미지 리소스를 불러올 때는
Picture를 사용한다.3주차 과제 조사 차 타이젠 플랫폼에서의 ThorVG 사용 확인 시에도,
위와 같이 SVG, Lottie 같은 리소스들을 쓸 때, 복잡한 벡터 콘텐츠를 픽셀 텍스처로 만드는데 사용하고있었고,
이 때
Picutre::load를 사용했다.참고로 파일이 아니라 메모리에 있는 데이터를 직접 전달할 수도 있다.
SVG와 Lottie 같은 vector 리소스뿐 아니라 PNG, JPEG, WebP 같은 bitmap 리소스도 같은 Public API로 불러올 수 있다.
이 때 Public
Picture::load()이 입력을 직접 해석하지 않고 Shape때와 같이 내부 구현인PictureImpl::load()로 요청을 넘긴다는 점.따라서 loader 동작을 추적할 때는
tvgPicture.cpp의 Public API를 확인한 뒤tvgPicture.h의PictureImpl를 확인.Picture::load(filename),Picture::load(data, ...)사용자가
Picture::load()에 SVG 리소스를 전달하면, ThorVG 내부에서는 어떤 과정을 거쳐 SVG loader와 parser에 도달할지.2. LoaderMgr : 입력에 맞는 loader를 선택한다
PictureImpl은 SVG loader를 직접 생성하지 않는다. 입력 데이터와 부가 정보를LoaderMgr에 전달한다.이 때
LoaderMgr는 입력 형태에 따라 적절한 loader를 찾는다..svg,.png,.jpg같은 확장자를 확인한다."svg","png"같은 mimeType을 우선 확인한다.SVG 입력이라면 최종적으로
SvgLoader가 선택된다.3. 공통 Loader와 SVG Loader의 역할
ThorVG의 각 loader는 공통
Loader인터페이스를 기반으로 동작한다.전체 흐름은 대충 아래 3단계가 큰 흐름이다.
이미지 loader는 처리 결과에 따라 크게 두 종류로 볼 수 있는데,
loader는 원본 리소스를 읽고 해석하는 객체,
vector는 SVG처럼 Paint와 Scene으로 변환된 결과, (pixel로 바로 변환 x)
bitmap은 PNG처럼 pixel surface로 변환된 결과
이렇게 보면 될 것 같다.
PictureImpl은 loader와 변환 결과를 관리한다.코드:
PictureImpl의 loader/vector/bitmap 상태,메모리 입력을 LoaderMgr로 넘기는 지점4. SVG Loader는 헤더 확인과 전체 파싱을 나누어 처리한다
open()이 호출된다.header()는 입력에서<svg>태그를 찾고 width, height, viewBox 같은 기본 정보를 확인한다.read()가 전체 SVG 파싱 작업을 요청한다.즉
open()에서 전체 SVG를 모두 해석하는 것은 아니다.open()과header()는 입력이 SVG인지 확인하고 기본 정보를 얻는다.read()와run()은 전체 문서를 파싱하고 실제 그래픽 객체를 준비한다.SVG 전체 파싱은 task를 통해 진행되므로 loader 코드를 볼 때 작업 완료를 기다리는
done()또는sync()지점도 함께 확인할 필요가 있다.SvgLoader.h,메모리 입력 open(),파일 입력 open()SvgLoader::header()SvgLoader::read(),SvgLoader::run()5. SVG 문자열에서 ThorVG Scene까지
간략하게 말하면 문자열의 문법을 나누고 의미를 해석한 뒤 렌더링 가능한 Paint 그래프로 변환한다.
이 과정은 역할에 따라 세 부분으로 나누어서 보면 될 것 같다.
문자열을 나누는 parser
tvgXmlParser.cpp는 XML 태그, CSS block,key:value형태의 속성 문자열을 분리하고 callback을 호출한다.xmlParse(),xmlParseCSSAttribute(),xmlParseW3CAttribute()SVG 의미를 해석하는 loader
tvgSvgLoader.cpp는 parser가 전달한 태그와 속성이 SVG에서 무엇을 의미하는지 해석한다.파싱하는 세부 로직은 로더를 학습할 때 따로 더 봐야할 것 같고 일단 전체 구조 위주로..
위와 같은 svg가 있을 때, ThorVG에서는 바로 svg파일을 여는게 아니고,
아래와 같이
나누는 것.
이렇게 분리된
key와value는 callback을 통해 SVG loader로 전달되고SVG loader는
font-family를 폰트 이름으로,src를 폰트 리소스 정보로 해석해 데이터로 저장한다.이렇게 추출한 폰트 정보는 이후 SVG의 Text Paint를 구성할 때 활용된다. ( 데이터가 Text Paint에 그대로 들어가는 것은 아니고, SVG에 포함된 폰트를 등록한 뒤 Text Paint가 그 폰트를 사용할 수 있도록 연결하는 중간 정보로 사용된다. )
ThorVG 그래픽 객체를 만드는 builder
파싱과 후처리가 끝나면
svgSceneBuild()가 SVG 문서 모델을 ThorVG의Scene,Shape,Text,Picture같은Paint객체로 변환한다.만들어진 root
Scene은SvgLoader::paint()를 통해PictureImpl로 전달되고, 이후 renderer가 이 vector scene을 처리.정리
이번에는 loader 내부 구현을 모두 따라가기보다 Public API에서 SVG parser까지 이어지는 주요 경계를 확인.
이 큰 흐름을 기준으로 보면 loader 관련 코드를 확인할 때 다음 단계로 범위를 나눌 수 있다.
다음에는
svgSceneBuild()에서 SVG node 하나가 실제 ThorVGShape나Text로 변환되는 과정을 따라가 보면 좋을 것 같다.All reactions