diff options
| author | Jasper van de Gronde <jasper.vandegronde@gmail.com> | 2009-03-31 20:41:47 +0000 |
|---|---|---|
| committer | jaspervdg <jaspervdg@users.sourceforge.net> | 2009-03-31 20:41:47 +0000 |
| commit | 52ba7a652f9e84425f328719fe6fba138361b4b3 (patch) | |
| tree | a64e7aa1d3e0f345b65ce73a4cfa45896634427f /src | |
| parent | More sensitive selection of snap target when snapping guides to objects with ... (diff) | |
| download | inkscape-52ba7a652f9e84425f328719fe6fba138361b4b3.tar.gz inkscape-52ba7a652f9e84425f328719fe6fba138361b4b3.zip | |
Fix for helperfns_read_vector (which could go on trying to read numbers for ever) and some quality improvements to gradient rendering and feComponentTransfer handling.
(bzr r7599)
Diffstat (limited to 'src')
| -rw-r--r-- | src/display/nr-filter-component-transfer.cpp | 102 | ||||
| -rw-r--r-- | src/filters/componenttransfer.cpp | 1 | ||||
| -rw-r--r-- | src/helper-fns.h | 19 | ||||
| -rw-r--r-- | src/sp-gradient.cpp | 21 |
4 files changed, 86 insertions, 57 deletions
diff --git a/src/display/nr-filter-component-transfer.cpp b/src/display/nr-filter-component-transfer.cpp index 74d66fbe4..6f9e2b712 100644 --- a/src/display/nr-filter-component-transfer.cpp +++ b/src/display/nr-filter-component-transfer.cpp @@ -45,13 +45,10 @@ int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units int y0=in->area.y0; int y1=in->area.y1; - NRPixBlock *out = new NRPixBlock; - nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8N, x0, y0, x1, y1, true); - - // this primitive is defined for non-premultiplied RGBA values, + // this primitive is defined for RGBA values, // thus convert them to that format before blending bool free_in_on_exit = false; - if (in->mode != NR_PIXBLOCK_MODE_R8G8B8A8N) { + if (in->mode != NR_PIXBLOCK_MODE_R8G8B8A8N && in->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) { NRPixBlock *original_in = in; in = new NRPixBlock; nr_pixblock_setup_fast(in, NR_PIXBLOCK_MODE_R8G8B8A8N, @@ -61,6 +58,11 @@ int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units nr_blit_pixblock_pixblock(in, original_in); free_in_on_exit = true; } + bool premultiplied = in->mode == NR_PIXBLOCK_MODE_R8G8B8A8P; + g_message("Premultiplied=%s", premultiplied?"yes":"no"); + + NRPixBlock *out = new NRPixBlock; + nr_pixblock_setup_fast(out, in->mode, x0, y0, x1, y1, true); unsigned char *in_data = NR_PIXBLOCK_PX(in); unsigned char *out_data = NR_PIXBLOCK_PX(out); @@ -71,7 +73,8 @@ int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units int size = 4 * (y1-y0) * (x1-x0); int i; - for (int color=0;color<4;color++){ + int color=4; + while(color-->0) { int _vsize = tableValues[color].size(); double _intercept = intercept[color]; double _slope = slope[color]; @@ -93,15 +96,28 @@ int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units out_data[i]=in_data[i]; } } else { - std::vector<gdouble> _tableValues(tableValues[color]); - // Scale by 255 and add .5 to avoid having to add it later for rounding purposes - for(i=0;i<_vsize;i++) { - _tableValues[i] = std::max(0.,std::min(255.,255*_tableValues[i])) + .5; - } - for(i=color;i<size;i+=4){ - int k = FAST_DIVIDE<255>((_vsize-1) * in_data[i]); - double dx = ((_vsize-1) * in_data[i])/255.0 - k; - out_data[i] = static_cast<unsigned char>(_tableValues[k] + dx * (_tableValues[k+1] - _tableValues[k])); + if (!premultiplied || color==3) { + std::vector<gdouble> _tableValues(tableValues[color]); + // Scale by 255 and add .5 to avoid having to add it later for rounding purposes + for(i=0;i<_vsize;i++) { + _tableValues[i] = std::max(0.,std::min(255.,255*_tableValues[i])) + .5; + } + for(i=color;i<size;i+=4){ + int k = FAST_DIVIDE<255>((_vsize-1) * in_data[i]); + double dx = ((_vsize-1) * in_data[i])/255.0 - k; + out_data[i] = static_cast<unsigned char>(_tableValues[k] + dx * (_tableValues[k+1] - _tableValues[k])); + } + } else { + std::vector<gdouble> _tableValues(tableValues[color]); + for(i=0;i<_vsize;i++) { + _tableValues[i] = std::max(0.,std::min(1.,_tableValues[i])); + } + for(i=color;i<size;i+=4){ + if (in_data[i+3-color]==0) continue; + int k = ((_vsize-1) * in_data[i]) / in_data[i+3-color]; + double dx = ((_vsize-1) * in_data[i]) / (double)in_data[i+3-color] - k; + out_data[i] = static_cast<unsigned char>(out_data[i+3-color] * (_tableValues[k] + dx * (_tableValues[k+1] - _tableValues[k])) + .5); + } } } break; @@ -111,28 +127,54 @@ int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units out_data[i] = in_data[i]; } } else { - std::vector<unsigned char> _tableValues(_vsize); - // Convert to unsigned char - for(i=0;i<_vsize;i++) { - _tableValues[i] = static_cast<unsigned char>(std::max(0.,std::min(255.,255*tableValues[color][i])) + .5); - } - for(i=color;i<size;i+=4){ - int k = FAST_DIVIDE<255>((_vsize-1) * in_data[i]); - out_data[i] = _tableValues[k]; + if (!premultiplied || color==3) { + std::vector<unsigned char> _tableValues(_vsize); + // Convert to unsigned char + for(i=0;i<_vsize;i++) { + _tableValues[i] = static_cast<unsigned char>(std::max(0.,std::min(255.,255*tableValues[color][i])) + .5); + } + for(i=color;i<size;i+=4){ + int k = FAST_DIVIDE<255>((_vsize-1) * in_data[i]); + out_data[i] = _tableValues[k]; + } + } else { + std::vector<gdouble> _tableValues(tableValues[color]); + for(i=0;i<_vsize;i++) { + _tableValues[i] = std::max(0.,std::min(1.,_tableValues[i])); + } + for(i=color;i<size;i+=4){ + if (in_data[i+3-color]==0) continue; + int k = ((_vsize-1) * in_data[i]) / in_data[i+3-color]; + out_data[i] = static_cast<unsigned char>(out_data[i+3-color] * _tableValues[k] + .5); + } } } break; case COMPONENTTRANSFER_TYPE_LINEAR: - _intercept = 255*_intercept + .5; - for(i=color;i<size;i+=4){ - out_data[i] = CLAMP_D_TO_U8(_slope * in_data[i] + _intercept); + if (!premultiplied || color==3) { + _intercept = 255*_intercept + .5; + for(i=color;i<size;i+=4){ + out_data[i] = CLAMP_D_TO_U8(_slope * in_data[i] + _intercept); + } + } else { + for(i=color;i<size;i+=4){ + if (in_data[i+3-color]==0) continue; + out_data[i] = CLAMP_D_TO_U8(out_data[i+3-color] * (_slope * in_data[i] / in_data[i+3-color] + _intercept) + .5); + } } break; case COMPONENTTRANSFER_TYPE_GAMMA: - _amplitude *= pow(255.0, -_exponent+1); - _offset = 255*_offset + .5; - for(i=color;i<size;i+=4){ - out_data[i] = CLAMP_D_TO_U8(_amplitude * pow((double)in_data[i], _exponent) + _offset); + if (!premultiplied || color==3) { + _amplitude *= pow(255.0, -_exponent+1); // The input should be divided by 255, then exponentiated and then multiplied by 255 again, instead the amplitude is modified accordingly. + _offset = 255*_offset + .5; + for(i=color;i<size;i+=4){ + out_data[i] = CLAMP_D_TO_U8(_amplitude * pow((double)in_data[i], _exponent) + _offset); + } + } else { + for(i=color;i<size;i+=4){ + if (in_data[i+3-color]==0) continue; + out_data[i] = CLAMP_D_TO_U8(out_data[i+3-color] * (_amplitude * pow((double)in_data[i] / in_data[i+3-color], _exponent) + _offset) + .5); + } } break; case COMPONENTTRANSFER_TYPE_ERROR: diff --git a/src/filters/componenttransfer.cpp b/src/filters/componenttransfer.cpp index 162b67703..f2f68e05d 100644 --- a/src/filters/componenttransfer.cpp +++ b/src/filters/componenttransfer.cpp @@ -194,7 +194,6 @@ sp_feComponentTransfer_set(SPObject *object, unsigned int key, gchar const *valu ((SPObjectClass *) feComponentTransfer_parent_class)->set(object, key, value); break; } - } /** diff --git a/src/helper-fns.h b/src/helper-fns.h index 9d3380bf2..18e065a8d 100644 --- a/src/helper-fns.h +++ b/src/helper-fns.h @@ -94,24 +94,23 @@ inline std::vector<gdouble> helperfns_read_vector(const gchar* value, int size){ */ inline std::vector<gdouble> helperfns_read_vector(const gchar* value){ std::vector<gdouble> v; - std::istringstream is(value); - gdouble d; - std::string str; - is >> str; - while(str.size()) + gchar const* beg = value; + while(isspace(*beg)) beg++; + while(*beg) { char *end; - double ret = g_strtod(str.c_str(), &end); - if (*end){ - g_warning("helper-fns::helperfns_read_vector() Unable to convert \"%s\" to number", str.c_str()); + double ret = g_strtod(beg, &end); + if (end==beg){ + g_warning("helper-fns::helperfns_read_vector() Unable to convert \"%s\" to number", beg); // We could leave this out, too. If strtod can't convert // anything, it will return zero. ret = 0; } - v.push_back(d); + v.push_back(ret); - is >> str; + beg = end; + while(isspace(*beg)) beg++; } return v; } diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp index 5c973cf0d..3abb91690 100644 --- a/src/sp-gradient.cpp +++ b/src/sp-gradient.cpp @@ -30,6 +30,7 @@ #include <sigc++/adaptors/bind.h> #include "libnr/nr-gradient.h" +#include "libnr/nr-pixops.h" #include "svg/svg.h" #include "svg/svg-color.h" #include "svg/css-ostringstream.h" @@ -1098,23 +1099,11 @@ sp_gradient_ensure_colors(SPGradient *gr) gint o0 = (gint) floor(gr->vector.stops[i].offset * (NCOLORS - 0.001)); gint o1 = (gint) floor(gr->vector.stops[i + 1].offset * (NCOLORS - 0.001)); if (o1 > o0) { - gint dr = ((r1 - r0) << 16) / (o1 - o0); - gint dg = ((g1 - g0) << 16) / (o1 - o0); - gint db = ((b1 - b0) << 16) / (o1 - o0); - gint da = ((a1 - a0) << 16) / (o1 - o0); - gint r = r0 << 16; - gint g = g0 << 16; - gint b = b0 << 16; - gint a = a0 << 16; for (int j = o0; j < o1 + 1; j++) { - gr->color[4 * j] = r >> 16; - gr->color[4 * j + 1] = g >> 16; - gr->color[4 * j + 2] = b >> 16; - gr->color[4 * j + 3] = a >> 16; - r += dr; - g += dg; - b += db; - a += da; + gr->color[4 * j + 0] = r0 + DIV_ROUND((j-o0)*(r1-r0),(o1-o0)); + gr->color[4 * j + 1] = g0 + DIV_ROUND((j-o0)*(g1-g0),(o1-o0)); + gr->color[4 * j + 2] = b0 + DIV_ROUND((j-o0)*(b1-b0),(o1-o0)); + gr->color[4 * j + 3] = a0 + DIV_ROUND((j-o0)*(a1-a0),(o1-o0)); } } } |
