svifylabs / fog

Automatically exported from code.google.com/p/fog
1 stars 0 forks source link

Various Fills getting white lines #17

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago

Attached shows you the source document TestPaint.ref.pdf and the results when 
rendered using Fog.  

I could have a coordinate issue or it could be just that SPREAD_PAD is not 
working.

Any thoughts?

Original issue reported on code.google.com by marietta...@peernet.com on 23 Nov 2010 at 5:45

Attachments:

GoogleCodeExporter commented 9 years ago
Hi,

Are we talking about the white lines in pattern and small white patterns in 
gradients? I see the issue and I'd like to catch it.

Thank you!

Original comment by kobalicek.petr on 24 Nov 2010 at 9:01

GoogleCodeExporter commented 9 years ago
Yes, I am talking about those white lines.

In AGG 2.4 had this same problem but then AGG 2.5 was released, the image fill 
was fixed.

In AGG, I was able to create span generators which was useful for creating 
shading patterns that were truely smooth filled (no color stops).  See attached 
example below:   Is this possible with FOG-GRAPHICS?

//==========================================================span_gradient
template<class ColorT,
         class Interpolator,
         class Allocator = span_allocator<ColorT> >
class span_radial_shading : public agg::span_generator<ColorT, Allocator>
{
public:
    typedef Interpolator interpolator_type;
    typedef Allocator alloc_type;
    typedef ColorT color_type;
    typedef agg::span_generator<color_type, alloc_type> base_type;

    GfxState        *m_gfxstate ;
    GfxRadialShading *m_shading ;
    AggClip         *m_pClip ;

    double xMin, yMin, xMax, yMax ;
    double x0, y0, r0, x1, y1, r1 ;
    double t0, t1 ;

    double tMin, tMax ;
    double dx, dy, dr ;

    double C ;

    double c0_c1 ;
    double r1_2 ;
    int aligned_circles ;

    bool bExtend0 ;
    bool bExtend1 ;

    //--------------------------------------------------------------------
    span_radial_shading(alloc_type& alloc) : base_type(alloc) {}

    //--------------------------------------------------------------------
    span_radial_shading(alloc_type& alloc,
                  interpolator_type& inter, 
                  AggClip         *pClip,
                  GfxState *gfxstate, 
                  GfxRadialShading  *shading )  : 
        base_type(alloc),
        m_interpolator(&inter)
    {
        m_pClip = pClip ;
        m_gfxstate = gfxstate ;
        m_shading = shading ;

        // get the clip region bbox
        gfxstate->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);

        // compute min and max t values, based on the four corners of the
        // clip region bbox
        m_shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1 );

        dx = x1 - x0;
        dy = y1 - y0;
        dr = r1 - r0 ;

        C = dx*dx + dy*dy - dr*dr ;

        // get the function domain
        t0 = shading->getDomain0();
        t1 = shading->getDomain1();

        x1 = x0 ;

        if (x0 != x1 || y0 != y1) {
            aligned_circles = 0;
            dx = x1 - x0;
            dy = y1 - y0;
            c0_c1 = sqrt (dx * dx + dy * dy);
            r1_2 = r1 * r1;
        } else {
            aligned_circles = 1;
            r1 = 1.0 / (r1 - r0);
            r1_2 = c0_c1 = 0.0; /* shut up compiler */
        }

        bExtend0 = shading->getExtend0() != gFalse ;
        bExtend1 = shading->getExtend1() != gFalse ;

    }

    //--------------------------------------------------------------------
    interpolator_type& interpolator() { return *m_interpolator; }

    //--------------------------------------------------------------------
    void interpolator(interpolator_type& i) { m_interpolator = &i; }

    //--------------------------------------------------------------------
    color_type* generate(int x, int y, unsigned len)
    {   
        color_type* span = base_type::allocator().span();

        m_interpolator->begin(x+0.5, y+0.5, len);
        do
        {
            // Compute the color at x and y for this shading function!!

            m_interpolator->coordinates(&x, &y); // Map x and y between x0,y0 and x1,y1

            double posx = x / 256.0 ;
            double posy = y / 256.0;

            double px = posx;
            double py = posy ;

            /* transform fragment into pattern space!! */
//          double ex = a * px + c * py + tx;
//          double ey = b * px + d * py + ty;

            double ex = px;
            double ey = py;
            double factor ;

            // Rotate ex, ey so that circles are aligned!!
            // the calculate factor

            if ( ! aligned_circles ) {
                //x1 = x0 and y1 = y0 
                agg::trans_affine mtx ;
                mtx *= agg::trans_affine_translation( -x0, -y0 ) ;
            //  mtx *= agg::trans_affine_rotation(  ) ;
                mtx *= agg::trans_affine_translation( x0, y0 ) ;

            }

            // this works only if c0 is inside c1 !!!

            if (aligned_circles) {
                ex = ex - x1;
                ey = ey - y1;

                factor = (sqrt (ex * ex + ey * ey) - r0) * r1;
            } else {
                /*
                            y         (ex, ey)
                       c0 -------------------+---------- x
                          \     |                  __--
                           \    |              __--
                            \   |          __--
                             \  |      __-- r1
                              \ |  __--
                              c1 --

                   We need to calulate distance c0->x; the distance from
                   the inner circle center c0, through fragment position
                   (ex, ey) to point x where it crosses the outer circle.

                   From points c0, c1 and (ex, ey) we get angle C0. With
                   angle C0 we calculate distance c1->y and c0->y and by
                   knowing c1->y and r1, we also know y->x. Adding y->x to
                   c0->y gives us c0->x. The gradient offset can then be
                   calculated as:

                   offset = (c0->e - r0) / (c0->x - r0)

                   */

                double  c0_e_x, c0_e_y, c0_e, c1_e_x, c1_e_y, c1_e ;
                double  angle_c0 ;
                double  c1_y, y_x, c0_y, c0_x ;
                double denumerator ;
                double fraction ;

                c0_e_x = ex - x0;
                c0_e_y = ey - y0;
                c0_e = sqrt (c0_e_x * c0_e_x + c0_e_y * c0_e_y);

                c1_e_x = ex - x1;
                c1_e_y = ey - y1;
                c1_e = sqrt (c1_e_x * c1_e_x + c1_e_y * c1_e_y);

                denumerator = -2.0 * c0_e * c0_c1;

                if (denumerator != 0.0) {

                    fraction = (c1_e * c1_e - c0_e * c0_e - c0_c1 * c0_c1) / denumerator;

                    if (fraction > 1.0)
                        fraction = 1.0;
                    else if (fraction < -1.0)
                        fraction = -1.0;

                    angle_c0 = acos (fraction);

                    c0_y = cos (angle_c0) * c0_c1 ;
                    c1_y = sin (angle_c0) * c0_c1 ;

                    y_x = sqrt (r1_2 - c1_y * c1_y);
                    c0_x = y_x + c0_y;

                    if ( c0_y > 0 )
                        factor = (c0_e - r0) / (c0_x - r0);
                    else
                        factor = 0 ;

                } else {
                    factor = -r0;
                }
            }

            double t = t0 + factor * (t1 - t0) ;

            if ( t < t0 ) {
                if ( ! bExtend0 )
                    t = -1 ;
                else
                    t = t0 ;
            } else if ( t > t1 ) {
                if ( ! bExtend1 )
                    t = -1 ;
                else
                    t = t1 ;
            }

            if ( t < 0 ) {
                // Not colored - set to white with no alpha?
                *span++ = (color_type)(agg::rgba8(0, 255, 0 ,255 )) ;
//              *span++ = (color_type)(agg::rgba8(255, 255, 255 ,0  )) ;
            } else {

                GfxColor color0 ;
                m_shading->getColor( t, &color0 ) ;

                m_gfxstate->setFillColor(&color0);

                GfxRGB rgb;
                m_gfxstate->getFillRGB(&rgb);

                *span++ = (color_type)(agg::rgba8(colToByte(rgb.r),
                                                    colToByte(rgb.g),
                                                    colToByte(rgb.b), 255 )) ;
            }

            ++(*m_interpolator);
        }
        while(--len);

        return base_type::allocator().span();
    }

private:
    interpolator_type* m_interpolator;
};

Original comment by marietta...@peernet.com on 24 Nov 2010 at 10:11

GoogleCodeExporter commented 9 years ago
Hi Marietta,

This issue is not related to the AGG, because span fillers were written from 
the scratch. I think that it's only minor issue, I will catch it.

And about your code, I don't know what it does, do you have some example of it? 
(I mean image rendered through it).

Thanks!
Petr

Original comment by kobalicek.petr on 24 Nov 2010 at 10:42

GoogleCodeExporter commented 9 years ago

Code above show a sample of radial shading operator for PDF and Postscript.

I have similar code for axial shading operator for PDF and Postscript. 

The result it true smooth shading and any resolution.

This is not to say color stop based gradients can not simulate smooth shading 
so I have to expriement with this style of fill to get a better understanding 
of them and how they related to PDF and Postscript smooth fill operators.

Original comment by marietta...@peernet.com on 25 Nov 2010 at 12:50

Attachments:

GoogleCodeExporter commented 9 years ago
Hi Marietta,

this type of gradient can be rendered using two color stops at [0.0 and 1.0]. 
The only thing that is not supported at this time is radius of inner circle 
(starting at focal point) and selecting background color (when SPREAD_NONE is 
used).

I don't know if I add support for inner circle radius, but the background color 
will be implemented in future versions of Fog-Framework (for all patterns). 
Maybe the inner circle radius will be added too, but at this time I have not 
done mathematics for this.

Original comment by kobalicek.petr on 26 Nov 2010 at 7:45

GoogleCodeExporter commented 9 years ago
It's not that simple for the color as the shading dictionary in PDF is a 
function returns color values based on the value of t.  You need to read the 
attached technical note to understand what I am saming.

Also, it is in the PDF Reference guide.

To further mess us all up they also allow patterns to be one size but move in a 
specified step so pattern fills are not steps are not always one to one with 
the pattern size.   This is also a feature the tends never to be part of any 
graphics library and has to be emmulated using other techniques.

By the way I am Robert Massart, just we use only one Google account.

Petr, thanks for your looking at this.

Original comment by marietta...@peernet.com on 26 Nov 2010 at 2:06

Attachments:

GoogleCodeExporter commented 9 years ago
I optimized the shaded fill to use linear gradient fill with color stops but if 
you skew the transform as shown in upper left you get all blue and not the red 
to blue fill as expected. 

Original comment by marietta...@peernet.com on 26 Nov 2010 at 9:02

Attachments:

GoogleCodeExporter commented 9 years ago
If may understanding is correct about radial, you do not have an equivalent for:

cairo_pattern_t *
cairo_pattern_create_radial (double cx0, double cy0, double radius0,
                 double cx1, double cy1, double radius1)

Original comment by marietta...@peernet.com on 26 Nov 2010 at 9:34

GoogleCodeExporter commented 9 years ago
Hi Robert,

Sorry for delay.

I can confirm that there is no equivalent to cairo_pattern_create_radial in 
Fog, but that version would be useful in the future (I'd like to make my best 
for compatibility with other libs).

I can also confirm that when affine transform is used and it's skew then 
gradient rendering is not correct, this will be fixed of course by new painter 
architecture. Maybe this is your problem at this time.

BTW: Currently Fog doesn't allow to create color interpolator based on 
function, but when shaders will be complete I think that it will be possible 
(but this is long-time feature).

Accepting as "gradient transform issue". Thank You!

Original comment by kobalicek.petr on 9 Dec 2010 at 5:49

GoogleCodeExporter commented 9 years ago
Any update on when the new painter update will be available?

I know it's tricky business but I am trying to plan whether to proceed with fog 
or go another route

Original comment by marietta...@peernet.com on 8 Jan 2011 at 2:25

GoogleCodeExporter commented 9 years ago
Hi Robert,

I'm still working on it, the only thing that remains is the raster-painter 
engine, everything else is refactorized/compilable. I know that my work is 
slow, but please be patient;)

Original comment by kobalicek.petr on 12 Jan 2011 at 1:08

GoogleCodeExporter commented 9 years ago
Any idea at this point when you might be ready for us to start testing your 
changes?

Original comment by marietta...@peernet.com on 1 Feb 2011 at 1:56

GoogleCodeExporter commented 9 years ago
Hi Robert,

7 days? I'm getting closer! Thanks for your patience;)

Original comment by kobalicek.petr on 5 Feb 2011 at 1:57

GoogleCodeExporter commented 9 years ago
Any Luck?

Original comment by marietta...@peernet.com on 18 Feb 2011 at 1:51

GoogleCodeExporter commented 9 years ago
I'm making my best, really

Original comment by kobalicek.petr on 22 Feb 2011 at 11:25

GoogleCodeExporter commented 9 years ago
I know, but is there nothing I can do to help?

Original comment by marietta...@peernet.com on 24 Feb 2011 at 1:15