thorvg/src/lib/tvgShapeImpl.h
Hermet Park 8ed9edd33e common: code refactoring
keep consistency of internal functions among the paint type methods.

Change-Id: I98a42ac398ddc5aaf49ac59e5cbb1790266bd612
2020-07-29 20:49:59 +09:00

247 lines
No EOL
6.5 KiB
C

/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef _TVG_SHAPE_IMPL_H_
#define _TVG_SHAPE_IMPL_H_
#include "tvgCommon.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
struct ShapeStroke
{
float width = 0;
uint8_t color[4] = {0, 0, 0, 0};
float* dashPattern = nullptr;
uint32_t dashCnt = 0;
StrokeCap cap = StrokeCap::Square;
StrokeJoin join = StrokeJoin::Bevel;
~ShapeStroke()
{
if (dashPattern) free(dashPattern);
}
};
struct Shape::Impl
{
ShapePath *path = nullptr;
Fill *fill = nullptr;
ShapeStroke *stroke = nullptr;
RenderTransform *rTransform = nullptr;
uint8_t color[4] = {0, 0, 0, 0}; //r, g, b, a
uint32_t flag = RenderUpdateFlag::None;
void *edata = nullptr; //engine data
Shape *shape = nullptr;
Impl(Shape* s) : path(new ShapePath), shape(s)
{
}
~Impl()
{
if (path) delete(path);
if (fill) delete(fill);
if (stroke) delete(stroke);
if (rTransform) delete(rTransform);
}
bool dispose(RenderMethod& renderer)
{
return renderer.dispose(*shape, edata);
}
bool render(RenderMethod& renderer)
{
return renderer.render(*shape, edata);
}
bool update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t pFlag)
{
if (flag & RenderUpdateFlag::Transform) {
if (!rTransform) return false;
if (!rTransform->update()) {
delete(rTransform);
rTransform = nullptr;
}
}
if (rTransform && pTransform) {
RenderTransform outTransform(pTransform, rTransform);
edata = renderer.prepare(*shape, edata, &outTransform, static_cast<RenderUpdateFlag>(pFlag | flag));
} else {
auto outTransform = pTransform ? pTransform : rTransform;
edata = renderer.prepare(*shape, edata, outTransform, static_cast<RenderUpdateFlag>(pFlag | flag));
}
flag = RenderUpdateFlag::None;
if (edata) return true;
return false;
}
bool bounds(float* x, float* y, float* w, float* h)
{
if (!path) return false;
return path->bounds(x, y, w, h);
}
bool scale(float factor)
{
if (rTransform) {
if (fabsf(factor - rTransform->scale) <= FLT_EPSILON) return true;
} else {
if (fabsf(factor) <= FLT_EPSILON) return true;
rTransform = new RenderTransform();
if (!rTransform) return false;
}
rTransform->scale = factor;
if (!rTransform->overriding) flag |= RenderUpdateFlag::Transform;
return true;
}
bool rotate(float degree)
{
if (rTransform) {
if (fabsf(degree - rTransform->degree) <= FLT_EPSILON) return true;
} else {
if (fabsf(degree) <= FLT_EPSILON) return true;
rTransform = new RenderTransform();
if (!rTransform) return false;
}
rTransform->degree = degree;
if (!rTransform->overriding) flag |= RenderUpdateFlag::Transform;
return true;
}
bool translate(float x, float y)
{
if (rTransform) {
if (fabsf(x - rTransform->x) <= FLT_EPSILON && fabsf(y - rTransform->y) <= FLT_EPSILON) return true;
} else {
if (fabsf(x) <= FLT_EPSILON && fabsf(y) <= FLT_EPSILON) return true;
rTransform = new RenderTransform();
if (!rTransform) return false;
}
rTransform->x = x;
rTransform->y = y;
if (!rTransform->overriding) flag |= RenderUpdateFlag::Transform;
return true;
}
bool transform(const Matrix& m)
{
if (!rTransform) {
rTransform = new RenderTransform();
if (!rTransform) return false;
}
rTransform->override(m);
flag |= RenderUpdateFlag::Transform;
return true;
}
bool strokeWidth(float width)
{
//TODO: Size Exception?
if (!stroke) stroke = new ShapeStroke();
if (!stroke) return false;
stroke->width = width;
flag |= RenderUpdateFlag::Stroke;
return true;
}
bool strokeCap(StrokeCap cap)
{
if (!stroke) stroke = new ShapeStroke();
if (!stroke) return false;
stroke->cap = cap;
flag |= RenderUpdateFlag::Stroke;
return true;
}
bool strokeJoin(StrokeJoin join)
{
if (!stroke) stroke = new ShapeStroke();
if (!stroke) return false;
stroke->join = join;
flag |= RenderUpdateFlag::Stroke;
return true;
}
bool strokeColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
if (!stroke) stroke = new ShapeStroke();
if (!stroke) return false;
stroke->color[0] = r;
stroke->color[1] = g;
stroke->color[2] = b;
stroke->color[3] = a;
flag |= RenderUpdateFlag::Stroke;
return true;
}
bool strokeDash(const float* pattern, uint32_t cnt)
{
assert(pattern);
if (!stroke) stroke = new ShapeStroke();
if (!stroke) return false;
if (stroke->dashCnt != cnt) {
if (stroke->dashPattern) free(stroke->dashPattern);
stroke->dashPattern = nullptr;
}
if (!stroke->dashPattern) stroke->dashPattern = static_cast<float*>(malloc(sizeof(float) * cnt));
assert(stroke->dashPattern);
for (uint32_t i = 0; i < cnt; ++i)
stroke->dashPattern[i] = pattern[i];
stroke->dashCnt = cnt;
flag |= RenderUpdateFlag::Stroke;
return true;
}
ITransformMethod* transformMethod()
{
return new TransformMethod<Shape::Impl>(this);
}
};
#endif //_TVG_SHAPE_IMPL_H_