diff --git a/src/examples/Opacity.cpp b/src/examples/Opacity.cpp index 9a78edd8..3ea66715 100644 --- a/src/examples/Opacity.cpp +++ b/src/examples/Opacity.cpp @@ -62,9 +62,9 @@ void tvgDrawCmds(tvg::Canvas* canvas) //Circle auto shape4 = tvg::Shape::gen(); - auto cx = 550.0f; - auto cy = 550.0f; - auto radius = 125.0f; + auto cx = 150.0f; + auto cy = 150.0f; + auto radius = 50.0f; auto halfRadius = radius * 0.552284f; //Append Paths @@ -77,6 +77,7 @@ void tvgDrawCmds(tvg::Canvas* canvas) shape4->stroke(10); shape4->stroke(0, 0, 255, 255); shape4->opacity(200); + shape4->scale(3); scene2->push(move(shape4)); //Draw the Scene onto the Canvas diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index b8110ee4..cd91f66e 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -211,7 +211,7 @@ SwRenderer::~SwRenderer() { clear(); - if (mainSurface) delete(mainSurface); + if (surface) delete(surface); --rendererCnt; if (!initEngine) _termEngine(); @@ -237,24 +237,24 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t { if (!buffer || stride == 0 || w == 0 || h == 0) return false; - if (!mainSurface) { - mainSurface = new SwSurface; - if (!mainSurface) return false; + if (!surface) { + surface = new SwSurface; + if (!surface) return false; } - mainSurface->buffer = buffer; - mainSurface->stride = stride; - mainSurface->w = w; - mainSurface->h = h; - mainSurface->cs = cs; + surface->buffer = buffer; + surface->stride = stride; + surface->w = w; + surface->h = h; + surface->cs = cs; - return rasterCompositor(mainSurface); + return rasterCompositor(surface); } bool SwRenderer::preRender() { - return rasterClear(mainSurface); + return rasterClear(surface); } @@ -262,13 +262,6 @@ bool SwRenderer::postRender() { tasks.clear(); - //Clear Composite Surface - if (compSurface) { - if (compSurface->buffer) free(compSurface->buffer); - delete(compSurface); - } - compSurface = nullptr; - return true; } @@ -278,7 +271,7 @@ bool SwRenderer::render(TVG_UNUSED const Picture& picture, void *data) auto task = static_cast(data); task->done(); - return rasterImage(mainSurface, &task->image, task->transform, task->opacity); + return rasterImage(surface, &task->image, task->transform, task->opacity); } @@ -288,7 +281,7 @@ void* SwRenderer::beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h) if (!ctx) return nullptr; //SwImage, Optimize Me: Surface size from MainSurface(WxH) to Parameter W x H - ctx->image.data = (uint32_t*) malloc(sizeof(uint32_t) * mainSurface->w * mainSurface->h); + ctx->image.data = (uint32_t*) malloc(sizeof(uint32_t) * surface->w * surface->h); if (!ctx->image.data) { delete(ctx); return nullptr; @@ -297,26 +290,26 @@ void* SwRenderer::beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h) //Boundary Check if (x < 0) x = 0; if (y < 0) y = 0; - if (x + w > mainSurface->w) w = (mainSurface->w - x); - if (y + h > mainSurface->h) h = (mainSurface->h - y); + if (x + w > surface->w) w = (surface->w - x); + if (y + h > surface->h) h = (surface->h - y); //FIXME: Should be removed if xywh is proper. x = 0; y = 0; - w = mainSurface->w; - h = mainSurface->h; + w = surface->w; + h = surface->h; ctx->image.bbox.min.x = x; ctx->image.bbox.min.y = y; ctx->image.bbox.max.x = x + w; ctx->image.bbox.max.y = y + h; - ctx->image.w = mainSurface->w; - ctx->image.h = mainSurface->h; + ctx->image.w = surface->w; + ctx->image.h = surface->h; //Inherits attributes from main surface - ctx->surface.comp = mainSurface->comp; - ctx->surface.stride = mainSurface->w; - ctx->surface.cs = mainSurface->cs; + ctx->surface.comp = surface->comp; + ctx->surface.stride = surface->w; + ctx->surface.cs = surface->cs; //We know partial clear region ctx->surface.buffer = ctx->image.data + (ctx->surface.stride * y + x); @@ -331,8 +324,8 @@ void* SwRenderer::beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h) ctx->surface.h = ctx->image.h; //Switch render target - ctx->recover = mainSurface; - mainSurface = &ctx->surface; + ctx->recover = surface; + surface = &ctx->surface; return ctx; } @@ -344,9 +337,9 @@ bool SwRenderer::endComposite(void* p, uint32_t opacity) auto ctx = static_cast(p); //Recover render target - mainSurface = ctx->recover; + surface = ctx->recover; - auto ret = rasterImage(mainSurface, &ctx->image, nullptr, opacity); + auto ret = rasterImage(surface, &ctx->image, nullptr, opacity); //Free resources free(ctx->image.data); @@ -356,54 +349,6 @@ bool SwRenderer::endComposite(void* p, uint32_t opacity) } -bool SwRenderer::prepareComposite(const SwShapeTask* task, SwImage* image) -{ - if (!compSurface) { - compSurface = new SwSurface; - if (!compSurface) return false; - *compSurface = *mainSurface; - compSurface->buffer = (uint32_t*) malloc(sizeof(uint32_t) * mainSurface->w * mainSurface->h); - if (!compSurface->buffer) { - delete(compSurface); - compSurface = nullptr; - return false; - } - } - - //Setup SwImage to return - image->data = compSurface->buffer; - image->w = compSurface->w; - image->h = compSurface->h; - image->rle = nullptr; - - //Add stroke size to bounding box. - auto strokeWidth = static_cast(ceilf(task->sdata->strokeWidth() * 0.5f)); - image->bbox.min.x = task->shape.bbox.min.x - strokeWidth; - image->bbox.min.y = task->shape.bbox.min.y - strokeWidth; - image->bbox.max.x = task->shape.bbox.max.x + strokeWidth; - image->bbox.max.y = task->shape.bbox.max.y + strokeWidth; - - if (image->bbox.min.x < 0) image->bbox.min.x = 0; - if (image->bbox.min.y < 0) image->bbox.min.y = 0; - if (image->bbox.max.x > image->w) image->bbox.max.x = image->w; - if (image->bbox.max.y > image->h) image->bbox.max.y = image->h; - - //We know partial clear region - compSurface->buffer = compSurface->buffer + (compSurface->stride * image->bbox.min.y) + image->bbox.min.x; - compSurface->w = image->bbox.max.x - image->bbox.min.x; - compSurface->h = image->bbox.max.y - image->bbox.min.y; - - rasterClear(compSurface); - - //Recover context - compSurface->buffer = image->data; - compSurface->w = image->w; - compSurface->h = image->h; - - return true; -} - - bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data) { auto task = static_cast(data); @@ -411,18 +356,21 @@ bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data) if (task->opacity == 0) return true; - SwSurface* renderTarget; - SwImage image; uint32_t opacity; + void *ctx = nullptr; //Do Composition if (task->compStroking) { - if (!prepareComposite(task, &image)) return false; - renderTarget = compSurface; + //Add stroke size to bounding box. + auto strokeWidth = static_cast(ceilf(task->sdata->strokeWidth() * 0.5f)); + auto x = task->shape.bbox.min.x - strokeWidth; + auto y = task->shape.bbox.min.y - strokeWidth; + auto w = task->shape.bbox.max.x + strokeWidth - x; + auto h = task->shape.bbox.max.y + strokeWidth - y; + ctx = beginComposite(x, y, w, h); opacity = 255; //No Composition } else { - renderTarget = mainSurface; opacity = task->opacity; } @@ -431,19 +379,19 @@ bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data) if (auto fill = task->sdata->fill()) { //FIXME: pass opacity to apply gradient fill? - rasterGradientShape(renderTarget, &task->shape, fill->id()); + rasterGradientShape(surface, &task->shape, fill->id()); } else{ task->sdata->fillColor(&r, &g, &b, &a); a = static_cast((opacity * (uint32_t) a) / 255); - if (a > 0) rasterSolidShape(renderTarget, &task->shape, r, g, b, a); + if (a > 0) rasterSolidShape(surface, &task->shape, r, g, b, a); } task->sdata->strokeColor(&r, &g, &b, &a); a = static_cast((opacity * (uint32_t) a) / 255); - if (a > 0) rasterStroke(renderTarget, &task->shape, r, g, b, a); + if (a > 0) rasterStroke(surface, &task->shape, r, g, b, a); //Composition (Shape + Stroke) stage - if (task->compStroking) rasterImage(mainSurface, &image, nullptr, task->opacity); + if (task->compStroking) endComposite(ctx, task->opacity); return true; } @@ -480,7 +428,7 @@ void SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, u } task->opacity = opacity; - task->surface = mainSurface; + task->surface = surface; task->flags = flags; tasks.push_back(task); diff --git a/src/lib/sw_engine/tvgSwRenderer.h b/src/lib/sw_engine/tvgSwRenderer.h index 19546a09..a7e50622 100644 --- a/src/lib/sw_engine/tvgSwRenderer.h +++ b/src/lib/sw_engine/tvgSwRenderer.h @@ -54,14 +54,12 @@ public: static bool term(); private: - SwSurface* mainSurface = nullptr; - SwSurface* compSurface = nullptr; //Composition Surface to use temporarily in the intermediate rendering + SwSurface* surface = nullptr; vector tasks; SwRenderer(){}; ~SwRenderer(); - bool prepareComposite(const SwShapeTask* task, SwImage* image); void prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, vector& compList, RenderUpdateFlag flags); };