Bug 691437 - Empty ResourceDictionary not handled.
Summary: Empty ResourceDictionary not handled.
Status: NOTIFIED FIXED
Alias: None
Product: GhostXPS
Classification: Unclassified
Component: General (show other bugs)
Version: master
Hardware: PC Windows XP
: P2 normal
Assignee: Tor Andersson
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-07-01 07:19 UTC by norbert.janssen
Modified: 2011-09-18 21:47 UTC (History)
0 users

See Also:
Customer: 661
Word Size: ---


Attachments
xps-job with empty ResourceDictionary. (39.88 KB, application/octet-stream)
2010-07-01 07:19 UTC, norbert.janssen
Details

Note You need to log in before you can comment on or make changes to this bug.
Description norbert.janssen 2010-07-01 07:19:19 UTC
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.
Comment 1 norbert.janssen 2010-07-01 07:24:39 UTC
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);
Comment 2 norbert.janssen 2010-07-01 07:48:51 UTC
(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
Comment 3 norbert.janssen 2010-07-01 11:07:47 UTC
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 */
	}
    }
}
Comment 4 Tor Andersson 2010-07-01 21:55:03 UTC
Fixed in r11478 and r11479, respectively.
Comment 5 Marcos H. Woehrmann 2011-09-18 21:47:39 UTC
Changing customer bugs that have been resolved more than a year ago to closed.