summaryrefslogtreecommitdiffstats
path: root/src/display
diff options
context:
space:
mode:
authorJasper van de Gronde <jasper.vandegronde@gmail.com>2009-03-31 20:41:47 +0000
committerjaspervdg <jaspervdg@users.sourceforge.net>2009-03-31 20:41:47 +0000
commit52ba7a652f9e84425f328719fe6fba138361b4b3 (patch)
treea64e7aa1d3e0f345b65ce73a4cfa45896634427f /src/display
parentMore sensitive selection of snap target when snapping guides to objects with ... (diff)
downloadinkscape-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/display')
-rw-r--r--src/display/nr-filter-component-transfer.cpp102
1 files changed, 72 insertions, 30 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: