Created attachment 6421 [details] xps-job with empty ResourceDictionary. In attached job (GradientStops.xps) there is an FixedPage.Resources with empty ResourceDictionary <FixedPage.Resources> <ResourceDictionary></ResourceDictionary> </FixedPage.Resources> In the xpspage.c (at line 233) the xps_parse_resourcedictionary() returns NULL , so a gs_rethrow(-1, "cannot load FixedPage.Resources") is done. So the job is not printed. The (MS) XPS-viewer though still prints the page. I think in case of an empty ResourceDictionary the rethrow() should not be done.
Also in this testjob out of bound GradientStops are used (-1.0, 2.0 etc). They should be clipped against 0.0 and 1.0 resp. The boxes on the left of the page should look the same as on the right of the page. gxps -sDEVICE=jpeg -sOutputFile=page%d.jpg GradientStop.xps fix in xpsgradient.xps if (!strcmp(xps_tag(node), "GradientStop")) { char *offset = xps_att(node, "Offset"); char *color = xps_att(node, "Color"); if (offset && color) { offsets[count] = atof(offset); /* clip stop-value against valid range */ if (offsets[count] < 0.0) offsets[count] = 0.0; if (offsets[count] > 1.0) offsets[count] = 1.0; xps_parse_color(ctx, base_uri, color, &colorspace, sample);
(In reply to comment #1) > Also in this testjob out of bound GradientStops are used (-1.0, 2.0 etc). They > should be clipped against 0.0 and 1.0 resp. > The boxes on the left of the page should look the same as on the right of the > page. > > gxps -sDEVICE=jpeg -sOutputFile=page%d.jpg GradientStop.xps > > fix in xpsgradient.xps > if (!strcmp(xps_tag(node), "GradientStop")) > { > char *offset = xps_att(node, "Offset"); > char *color = xps_att(node, "Color"); > if (offset && color) > { > offsets[count] = atof(offset); > > /* clip stop-value against valid range */ > if (offsets[count] < 0.0) > offsets[count] = 0.0; > if (offsets[count] > 1.0) > offsets[count] = 1.0; > > > xps_parse_color(ctx, base_uri, color, &colorspace, sample); Clipping is wrong (left boxes look different from right boxes). An interpolated value should have been used (see ch. 11.3.1.1 Gradient Stop Pre-Processing in the xps spec 1.0, page 239
After reading in the stops and sorting, still some rangechecking has to be done. Here my solution, to be inserted in xps_parse_gradient_stops() after sorting the offsets/colors arrays, just before returning 'count'; { float *from, *to; /* check for first stop 0.0 */ if (offsets[0] > 0.0) { /* add offset 0.0, with same color as next stop */ int tmp; for (tmp = count; tmp > 0; tmp--) { offsets[tmp] = offsets[tmp-1]; from = &colors[(tmp-1) * 4 + 0]; to = &colors[(tmp) * 4 + 0]; *to++ = *from++; *to++ = *from++; *to++ = *from++; *to = *from; } count++; } else if (offsets[0] < 0.0) { /* find location of 0.0 */ int tmp; for (tmp = 1; tmp < count; tmp++) { if (offsets[tmp] >= 0.0) break; } if ((tmp < count) && (offsets[tmp] == 0.0)) { int moveto; /* discard everything before tmp */ for (moveto = 0; tmp < count; tmp++, moveto++) { offsets[moveto] = offsets[tmp]; to = &colors[moveto * 4 + 0]; from = &colors[(tmp) * 4 + 0]; *to++ = *from++; *to++ = *from++; *to++ = *from++; *to = *from; } count -= tmp; } else if ((tmp < count) && (offsets[tmp] > 0.0)) { /* interpolate between tmp-1 and tmp * put it in tmp-1 * and discard everything before tmp-1 */ int moveto; float val1, val2, interval; val1 = offsets[tmp-1]; val2 = offsets[tmp]; interval = (0.0 - val1) / (val2 - val1); offsets[tmp-1] = 0.0; to = &colors[(tmp-1)*4 + 0]; from = &colors[tmp*4 + 0]; val1 = *to; *to += interval * (*from - val1); to++; from++; val1 = *to; *to += interval * (*from - val1); to++; from++; val1 = *to; *to += interval * (*from - val1); to++; from++; val1 = *to; *to += interval * (*from - val1); tmp--; /* offsets[tmp] = 0.0; */ if (tmp > 0) { /* discard everything before tmp */ for (moveto = 0; tmp < count; tmp++, moveto++) { float *from, *to; offsets[moveto] = offsets[tmp]; to = &colors[moveto * 4 + 0]; from = &colors[(tmp) * 4 + 0]; *to++ = *from++; *to++ = *from++; *to++ = *from++; *to = *from; } count -= tmp; } } else /* only values < 0.0 */ { /* add offset 0.0 with highest value color * discard everything below offset 0.0 */ offsets[0] = 0.0; to = &colors[0]; from = &colors[(count-1)*4 + 0]; *to++ = *from++; *to++ = *from++; *to++ = *from++; *to = *from; count = 1; } } /* check for last stop 1.0 */ /* at this point offsets[0] == 0.0 */ if (offsets[count-1] < 1.0) { /* add offset 1.0, with same color as previous stop */ offsets[count] = offsets[count-1]; to = &colors[count * 4 + 0]; from = &colors[(count-1) * 4 + 0]; *to++ = *from++; *to++ = *from++; *to++ = *from++; *to = *from; count++; } else if (offsets[count-1] > 1.0) { /* find location of 1.0 */ int tmp; for (tmp = count-2; tmp >= 0; tmp--) { if (offsets[tmp] <= 1.0) break; } if ((tmp > 0) && (offsets[tmp] == 1.0)) { /* discard everything after tmp */ count = tmp + 1; } else if ((tmp >= 0) && (offsets[tmp] < 1.0)) { /* interpolate between tmp and tmp+1 * put it in tmp+1 * and discard everything after tmp+1 */ float val1, val2, interval; val1 = offsets[tmp]; val2 = offsets[tmp+1]; interval = (val2 - 1.0) / (val2 - val1); offsets[tmp+1] = 1.0; to = &colors[(tmp+1)*4 + 0]; from = &colors[tmp*4+0]; val2 = *to; *to -= interval * (val2 - *from); to++; from++; val2 = *to; *to -= interval * (val2 - *from); to++; from++; val2 = *to; *to -= interval * (val2 - *from); to++; from++; val2 = *to; *to -= interval * (val2 - *from); tmp++; /* offsets[tmp] = 1.0; */ count = tmp+1; /* zero based */ } else /* only values > 1.0 */ { /* not possible, because in previous step a 0.0 was added */ } } }
Fixed in r11478 and r11479, respectively.
Changing customer bugs that have been resolved more than a year ago to closed.