mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
sw_engine: border cases for gradients
According to the svg standard, in a case when 'x1==x2 and y1==y2' for a linear gradient or when 'r==0' for a radial gradient, the area should be painted as a single color - the last gradient stop color.
This commit is contained in:
parent
fc29d888f1
commit
284298445b
2 changed files with 39 additions and 2 deletions
|
@ -6,9 +6,15 @@ project('thorvg',
|
||||||
|
|
||||||
config_h = configuration_data()
|
config_h = configuration_data()
|
||||||
|
|
||||||
|
if host_machine.system() != 'windows'
|
||||||
add_project_arguments('-DEXAMPLE_DIR="@0@/src/examples/images"'.format(meson.current_source_dir()),
|
add_project_arguments('-DEXAMPLE_DIR="@0@/src/examples/images"'.format(meson.current_source_dir()),
|
||||||
'-DTEST_DIR="@0@/test/images"'.format(meson.current_source_dir()),
|
'-DTEST_DIR="@0@/test/images"'.format(meson.current_source_dir()),
|
||||||
language : 'cpp')
|
language : 'cpp')
|
||||||
|
else
|
||||||
|
add_project_arguments('-DEXAMPLE_DIR="@0@\src\examples\images"'.format(meson.current_source_dir()),
|
||||||
|
'-DTEST_DIR="@0@\test\images"'.format(meson.current_source_dir()),
|
||||||
|
language : 'cpp')
|
||||||
|
endif
|
||||||
|
|
||||||
config_h.set_quoted('THORVG_VERSION_STRING', meson.project_version())
|
config_h.set_quoted('THORVG_VERSION_STRING', meson.project_version())
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <float.h>
|
||||||
#include "tvgSwCommon.h"
|
#include "tvgSwCommon.h"
|
||||||
#include "tvgTaskScheduler.h"
|
#include "tvgTaskScheduler.h"
|
||||||
#include "tvgSwRenderer.h"
|
#include "tvgSwRenderer.h"
|
||||||
|
@ -224,6 +225,18 @@ static void _termEngine()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool _monochromaticGradient(const Fill* fill)
|
||||||
|
{
|
||||||
|
float x1, x2, y1, y2, r;
|
||||||
|
|
||||||
|
if ((fill->id() == TVG_CLASS_ID_LINEAR && static_cast<const LinearGradient*>(fill)->linear(&x1, &y1, &x2, &y2) == Result::Success &&
|
||||||
|
fabsf(x1 - x2) < FLT_EPSILON && fabsf(y1 - y2) < FLT_EPSILON) ||
|
||||||
|
(fill->id() == TVG_CLASS_ID_RADIAL && static_cast<const RadialGradient*>(fill)->radial(nullptr, nullptr, &r) == Result::Success &&
|
||||||
|
r < FLT_EPSILON)) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
@ -364,7 +377,16 @@ bool SwRenderer::renderShape(RenderData data)
|
||||||
uint8_t r, g, b, a;
|
uint8_t r, g, b, a;
|
||||||
|
|
||||||
if (auto fill = task->sdata->fill()) {
|
if (auto fill = task->sdata->fill()) {
|
||||||
|
if (_monochromaticGradient(fill)) {
|
||||||
|
const Fill::ColorStop* stop;
|
||||||
|
auto cnt = fill->colorStops(&stop);
|
||||||
|
if (cnt > 0 && stop) {
|
||||||
|
a = static_cast<uint8_t>((opacity * static_cast<uint32_t>(stop[cnt - 1].a)) / 255);
|
||||||
|
if (a > 0) rasterSolidShape(surface, &task->shape, stop[cnt - 1].r, stop[cnt - 1].g, stop[cnt - 1].b, a);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
rasterGradientShape(surface, &task->shape, fill->id());
|
rasterGradientShape(surface, &task->shape, fill->id());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
task->sdata->fillColor(&r, &g, &b, &a);
|
task->sdata->fillColor(&r, &g, &b, &a);
|
||||||
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
||||||
|
@ -372,7 +394,16 @@ bool SwRenderer::renderShape(RenderData data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto strokeFill = task->sdata->strokeFill()) {
|
if (auto strokeFill = task->sdata->strokeFill()) {
|
||||||
|
if (_monochromaticGradient(strokeFill)) {
|
||||||
|
const Fill::ColorStop* stop;
|
||||||
|
auto cnt = strokeFill->colorStops(&stop);
|
||||||
|
if (cnt > 0 && stop) {
|
||||||
|
a = static_cast<uint8_t>((opacity * static_cast<uint32_t>(stop[cnt - 1].a)) / 255);
|
||||||
|
if (a > 0) rasterStroke(surface, &task->shape, stop[cnt - 1].r, stop[cnt - 1].g, stop[cnt - 1].b, a);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
rasterGradientStroke(surface, &task->shape, strokeFill->id());
|
rasterGradientStroke(surface, &task->shape, strokeFill->id());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (task->sdata->strokeColor(&r, &g, &b, &a) == Result::Success) {
|
if (task->sdata->strokeColor(&r, &g, &b, &a) == Result::Success) {
|
||||||
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
|
||||||
|
|
Loading…
Add table
Reference in a new issue