common loader: code refactoring

Bitmap based pictures doesn't need the viewbox,
LoaderModule should delegate the viewbox to the derived classes which
having vector-based image loaders such as svg, tvg.

In that case, paint resizing can be performed by the loaders by own
policy.
This commit is contained in:
Hermet Park 2021-07-28 14:06:55 +09:00 committed by Hermet Park
parent 3cb0caf2c4
commit d213a67180
9 changed files with 99 additions and 59 deletions

View file

@ -30,19 +30,17 @@ namespace tvg
class LoadModule
{
public:
//default view box, if any.
float vx = 0;
float vy = 0;
float vw = 0;
float vh = 0;
float w = 0, h = 0; //default image size
bool preserveAspect = true; //keep aspect ratio by default.
virtual ~LoadModule() {}
virtual bool open(const string& path) { return false; };
virtual bool open(const char* data, uint32_t size, bool copy) { return false; };
virtual bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) { return false; };
//Override this if the vector-format has own resizing policy.
virtual bool resize(Paint* paint, float w, float h) { return false; };
virtual bool read() = 0;
virtual bool close() = 0;
virtual const uint32_t* pixels() { return nullptr; };

View file

@ -76,37 +76,6 @@ struct Picture::Impl
return ret;
}
void resize()
{
auto sx = w / loader->vw;
auto sy = h / loader->vh;
if (loader->preserveAspect) {
//Scale
auto scale = sx < sy ? sx : sy;
paint->scale(scale);
//Align
auto vx = loader->vx * scale;
auto vy = loader->vy * scale;
auto vw = loader->vw * scale;
auto vh = loader->vh * scale;
if (vw > vh) vy -= (h - vh) * 0.5f;
else vx -= (w - vw) * 0.5f;
paint->translate(-vx, -vy);
} else {
//Align
auto vx = loader->vx * sx;
auto vy = loader->vy * sy;
auto vw = loader->vw * sx;
auto vh = loader->vh * sy;
if (vw > vh) vy -= (h - vh) * 0.5f;
else vx -= (w - vw) * 0.5f;
Matrix m = {sx, 0, -vx, 0, sy, -vy, 0, 0, 1};
paint->transform(m);
}
resizing = false;
}
uint32_t reload()
{
@ -115,7 +84,10 @@ struct Picture::Impl
if (auto p = loader->paint()) {
paint = p.release();
loader->close();
if (w != loader->w && h != loader->h) resize();
if (w != loader->w && h != loader->h) {
loader->resize(paint, w, h);
resizing = false;
}
if (paint) return RenderUpdateFlag::None;
}
}
@ -134,7 +106,10 @@ struct Picture::Impl
if (pixels) rdata = renderer.prepare(*picture, rdata, transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag));
else if (paint) {
if (resizing) resize();
if (resizing) {
loader->resize(paint, w, h);
resizing = false;
}
rdata = paint->pImpl->update(renderer, transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag));
}
return rdata;

View file

@ -79,8 +79,8 @@ bool JpgLoader::open(const string& path)
int width, height, subSample, colorSpace;
if (tjDecompressHeader3(jpegDecompressor, data, size, &width, &height, &subSample, &colorSpace) < 0) goto failure;
vw = w = static_cast<float>(width);
vh = h = static_cast<float>(height);
w = static_cast<float>(width);
h = static_cast<float>(height);
ret = true;
freeData = true;
@ -111,8 +111,8 @@ bool JpgLoader::open(const char* data, uint32_t size, bool copy)
this->data = (unsigned char *) data;
}
vw = w = static_cast<float>(width);
vh = h = static_cast<float>(height);
w = static_cast<float>(width);
h = static_cast<float>(height);
this->size = size;
return true;

View file

@ -45,8 +45,8 @@ bool PngLoader::open(const string& path)
if (!png_image_begin_read_from_file(image, path.c_str())) return false;
vw = w = image->width;
vh = h = image->height;
w = image->width;
h = image->height;
return true;
}
@ -57,8 +57,8 @@ bool PngLoader::open(const char* data, uint32_t size, bool copy)
if (!png_image_begin_read_from_memory(image, data, size)) return false;
vw = w = image->width;
vh = h = image->height;
w = image->width;
h = image->height;
return true;
}

View file

@ -45,14 +45,14 @@ bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy)
{
if (!data || w == 0 || h == 0) return false;
this->w = vw = w;
this->h = vh = h;
this->w = w;
this->h = h;
this->copy = copy;
if (copy) {
content = (uint32_t*)malloc(sizeof(uint32_t) * vw * vh);
content = (uint32_t*)malloc(sizeof(uint32_t) * w * h);
if (!content) return false;
memcpy((void*)content, data, sizeof(uint32_t) * vw * vh);
memcpy((void*)content, data, sizeof(uint32_t) * w * h);
}
else content = data;

View file

@ -2850,6 +2850,41 @@ bool SvgLoader::open(const string& path)
}
bool SvgLoader::resize(Paint* paint, float w, float h)
{
if (!paint) return false;
auto sx = w / vw;
auto sy = h / vh;
if (preserveAspect) {
//Scale
auto scale = sx < sy ? sx : sy;
paint->scale(scale);
//Align
auto vx = this->vx * scale;
auto vy = this->vy * scale;
auto vw = this->vw * scale;
auto vh = this->vh * scale;
if (vw > vh) vy -= (h - vh) * 0.5f;
else vx -= (w - vw) * 0.5f;
paint->translate(-vx, -vy);
} else {
//Align
auto vx = this->vx * sx;
auto vy = this->vy * sy;
auto vw = this->vw * sx;
auto vh = this->vh * sy;
if (vw > vh) vy -= (h - vh) * 0.5f;
else vx -= (w - vw) * 0.5f;
Matrix m = {sx, 0, -vx, 0, sy, -vy, 0, 0, 1};
paint->transform(m);
}
return true;
}
bool SvgLoader::read()
{
if (!content || size == 0) return false;

View file

@ -35,7 +35,14 @@ public:
SvgLoaderData loaderData;
unique_ptr<Scene> root;
//default view box, if any.
float vx = 0;
float vy = 0;
float vw = 0;
float vh = 0;
bool copy = false;
bool preserveAspect = true; //aspect ratio option
SvgLoader();
~SvgLoader();
@ -43,16 +50,15 @@ public:
using LoadModule::open;
bool open(const string& path) override;
bool open(const char* data, uint32_t size, bool copy) override;
bool header();
bool resize(Paint* paint, float w, float h) override;
bool read() override;
bool close() override;
void run(unsigned tid) override;
unique_ptr<Paint> paint() override;
private:
bool header();
void clear();
void run(unsigned tid) override;
};

View file

@ -85,6 +85,7 @@ bool TvgLoader::open(const string &path)
return tvgValidateData(pointer, size);
}
bool TvgLoader::open(const char *data, uint32_t size, bool copy)
{
clear();
@ -102,6 +103,30 @@ bool TvgLoader::open(const char *data, uint32_t size, bool copy)
return tvgValidateData(pointer, size);
}
bool TvgLoader::resize(Paint* paint, float w, float h)
{
if (!paint) return false;
auto sx = w / this->w;
auto sy = h / this->h;
//Scale
auto scale = sx < sy ? sx : sy;
paint->scale(scale);
//Align
float tx = 0, ty = 0;
auto sw = this->w * scale;
auto sh = this->h * scale;
if (sw > sh) ty -= (h - sh) * 0.5f;
else tx -= (w - sw) * 0.5f;
paint->translate(-tx, -ty);
return true;
}
bool TvgLoader::read()
{
if (!pointer || size == 0) return false;
@ -111,6 +136,7 @@ bool TvgLoader::read()
return true;
}
bool TvgLoader::close()
{
this->done();
@ -118,6 +144,7 @@ bool TvgLoader::close()
return true;
}
void TvgLoader::run(unsigned tid)
{
if (root) root.reset();
@ -125,6 +152,7 @@ void TvgLoader::run(unsigned tid)
if (!root) clear();
}
unique_ptr<Paint> TvgLoader::paint()
{
this->done();

View file

@ -31,9 +31,7 @@ public:
const char* data = nullptr;
const char* pointer = nullptr;
uint32_t size = 0;
unique_ptr<Scene> root = nullptr;
bool copy = false;
~TvgLoader();
@ -43,11 +41,11 @@ public:
bool open(const char *data, uint32_t size, bool copy) override;
bool read() override;
bool close() override;
void run(unsigned tid) override;
bool resize(Paint* paint, float w, float h) override;
unique_ptr<Paint> paint() override;
private:
void run(unsigned tid) override;
void clear();
};