Exemplo n.º 1
0
void
Bitmap::construct(as_object* /*init*/)
{
    if (_bitmapData) _bitmapData->attach(this);

    if (!_def && !_bitmapData) return;

    // Width and height are a maximum of 2880, so there is no risk of 
    // overflow 
    const int w = pixelsToTwips(_width);
    const int h = pixelsToTwips(_height);

    SWFMatrix mat;
    mat.set_scale(1.0 / 20, 1.0 / 20);

    // Can this be tiled? And smoothing?
    FillStyle fill = BitmapFill(BitmapFill::CLIPPED, bitmap(), mat,
            BitmapFill::SMOOTHING_UNSPECIFIED);

    const size_t fillLeft = _shape.addFillStyle(fill);

    Path bmpath(w, h, fillLeft, 0, 0, false);
    bmpath.drawLineTo(w, 0);
    bmpath.drawLineTo(0, 0);
    bmpath.drawLineTo(0, h);
    bmpath.drawLineTo(w, h);

    _shape.add_path(bmpath);
    _shape.finalize();

    set_invalidated();
}
Exemplo n.º 2
0
bool
Shape::pointInShape(boost::int32_t x, boost::int32_t y) const
{
    SWFMatrix wm = getWorldMatrix();
    wm.invert();
    point lp(x, y);
    wm.transform(lp);
    
    // FIXME: if the shape contains non-scaled strokes
    //        we can't rely on boundary itself for a quick
    //        way out. Bounds supposedly already include
    //        thickness, so we might keep a flag telling us
    //        whether *non_scaled* strokes are present
    //        and if not still use the boundary check.
    // NOTE: just skipping this test breaks a corner-case
    //       in DrawingApiTest (kind of a fill-leakage making
    //       the collision detection find you inside a self-crossing
    //       shape).
    if (_def) {
        if (!_def->bounds().point_test(lp.x, lp.y)) return false;
        return _def->pointTestLocal(lp.x, lp.y, wm);
    }
    assert(_shape.get());
    
    if (!_shape->getBounds().point_test(lp.x, lp.y)) return false;
    return _shape->pointTestLocal(lp.x, lp.y, wm);

}
Exemplo n.º 3
0
point
Renderer_gles1::pixel_to_world(int x, int y) const
{
    point p(x, y);
#if 0
    SWFMatrix mat = stage_matrix;
    mat.invert().transform(p);
    return p;
#endif

    return p;
};
Exemplo n.º 4
0
SWFMatrix
gradientMatrix(GradientFill::Type t, const SWFMatrix& m)
{
    SWFMatrix base;
    switch (t) {
        case GradientFill::LINEAR:
            base.set_translation(128, 0);
            base.set_scale(1.0 / 128, 1.0 / 128);
            break;
        case GradientFill::RADIAL:
            base.set_scale(1.0 / 512, 1.0 / 512);
            break;
    }
    base.concatenate(m);
    return base;
}
Exemplo n.º 5
0
bool
pointTest(const std::vector<Path>& paths,
        const std::vector<LineStyle>& lineStyles, boost::int32_t x,
        boost::int32_t y, const SWFMatrix& wm)
{

    /*
    Principle:
    For the fill of the shape, we project a ray from the test point to the left
    side of the shape counting all crossings. When a line or curve segment is
    crossed we add 1 if the left fill style is set. Regardless of the left fill
    style we subtract 1 from the counter then the right fill style is set.
    This is true when the line goes in downward direction. If it goes upward,
    the fill styles are reversed.

    The final counter value reveals if the point is inside the shape (and
    depends on filling rule, see below).
    This method should not depend on subshapes and work for some malformed
    shapes situations:
    - wrong fill side (eg. left side set for a clockwise drawen rectangle)
    - intersecting paths
    */
    point pt(x, y);

    // later we will need non-zero for glyphs... (TODO)
    bool even_odd = true;  

    unsigned npaths = paths.size();
    int counter = 0;

    // browse all paths
    for (unsigned pno=0; pno<npaths; pno++)
    {
        const Path& pth = paths[pno];
        unsigned nedges = pth.m_edges.size();

        float next_pen_x = pth.ap.x;
        float next_pen_y = pth.ap.y;
        float pen_x, pen_y;

        if (pth.empty()) continue;

        // If the path has a line style, check for strokes there
        if (pth.m_line != 0 )
        {
            assert(lineStyles.size() >= pth.m_line);
            const LineStyle& ls = lineStyles[pth.m_line-1];
            double thickness = ls.getThickness();
            if (! thickness )
            {
                thickness = 20; // at least ONE PIXEL thick.
            }
            else if ((!ls.scaleThicknessVertically()) &&
                    (!ls.scaleThicknessHorizontally()) )
            {
                // TODO: pass the SWFMatrix to withinSquareDistance instead ?
                double xScale = wm.get_x_scale();
                double yScale = wm.get_y_scale();
                thickness *= std::max(xScale, yScale);
            }
            else if (ls.scaleThicknessVertically() != 
                    ls.scaleThicknessHorizontally())
            {
                LOG_ONCE(log_unimpl(_("Collision detection for "
                                      "unidirectionally scaled strokes")));
            }

            double dist = thickness / 2.0;
            double sqdist = dist * dist;
            if (pth.withinSquareDistance(pt, sqdist))
                return true;
        }

        // browse all edges of the path
        for (unsigned eno=0; eno<nedges; eno++)
        {
            const Edge& edg = pth.m_edges[eno];
            pen_x = next_pen_x;
            pen_y = next_pen_y;
            next_pen_x = edg.ap.x;
            next_pen_y = edg.ap.y;

            float cross1 = 0.0, cross2 = 0.0;
            int dir1 = 0, dir2 = 0; // +1 = downward, -1 = upward
            int crosscount = 0;

            if (edg.straight())
            {
                // ignore horizontal lines
                // TODO: better check for small difference?
                if (edg.ap.y == pen_y)  
                {
                    continue;
                }
                // does this line cross the Y coordinate?
                if ( ((pen_y <= y) && (edg.ap.y >= y))
                    || ((pen_y >= y) && (edg.ap.y <= y)) )
                {

                    // calculate X crossing
                    cross1 = pen_x + (edg.ap.x - pen_x) *
                        (y - pen_y) / (edg.ap.y - pen_y);

                    if (pen_y > edg.ap.y)
                        dir1 = -1;  // upward
                    else
                        dir1 = +1;  // downward

                    crosscount = 1;
                }
                else
                {
                    // no crossing found
                    crosscount = 0;
                }
            }
            else {
                // ==> curve case
                crosscount = 
                    curve_x_crossings<float>(pen_x, pen_y, edg.ap.x, edg.ap.y,
                        edg.cp.x, edg.cp.y, y, cross1, cross2);
                dir1 = pen_y > y ? -1 : +1;
                dir2 = dir1 * (-1); // second crossing always in opposite dir.
            } // curve

            // ==> we have now:
            //  - one (cross1) or two (cross1, cross2) ray crossings (X
            //    coordinate)
            //  - dir1/dir2 tells the direction of the crossing
            //    (+1 = downward, -1 = upward)
            //  - crosscount tells the number of crossings

            // need at least one crossing
            if (crosscount == 0)
            {
                continue;
            }

            // check first crossing
            if (cross1 <= x)
            {
                if (pth.m_fill0 > 0) counter += dir1;
                if (pth.m_fill1 > 0) counter -= dir1;
            }

            // check optional second crossing (only possible with curves)
            if ( (crosscount > 1) && (cross2 <= x) )
            {
                if (pth.m_fill0 > 0) counter += dir2;
                if (pth.m_fill1 > 0) counter -= dir2;
            }

        }// for edge
    } // for path

    return ( (even_odd && (counter % 2) != 0) ||
             (!even_odd && (counter != 0)) );
}
Exemplo n.º 6
0
void
test_renderer(Renderer *renderer, const std::string &type)
{
    cout << "Testing " << type << " Renderer" << endl;
//    Timer trend("Renderer Tests", true);
    
    if (!renderer) {
        runtest.unresolved("No renderer to test!");
        return;
    }
    
    if (renderer > 0) {
        runtest.pass("Got Renderer");
    } else {
        runtest.fail("Couldn't get Renderer");
    }

    if (!renderer->description().empty()) {
        if (renderer->description() == type) {
            runtest.pass("description is correct");
        } else {
            runtest.fail("description is wrong");
        }
    } else {
        runtest.fail("Couldn't get description!");
    }

#if 0
    if (renderer->getBitsPerPixel()) {
        runtest.pass("getBitsPerPixel()");
    } else {
        runtest.fail("getBitsPerPixel()");
    }
#endif
    
    image::GnashImage *frame1 = new image::ImageRGBA(10, 12);
    std::auto_ptr<image::GnashImage> im1(frame1);
    CachedBitmap *cb = renderer->createCachedBitmap(im1);
    if (cb) {
        image::GnashImage &gi = cb->image();
        if ((gi.width() == 10) && (gi.height() == 12)) {
            runtest.pass("createCachedBitmap()");
        } else {
            runtest.fail("createCachedBitmap()");
        }
    } else {
        runtest.unresolved("createCachedBitmap()");
    }

#if 0
    // FIXME: initTestBuffer() is going away, replaced by the fake
    // framebuffer code.
    // Initializes the renderer for off-screen rendering used by the testsuite.
    if (renderer->initTestBuffer(10, 10)) {
        runtest.pass("initTestBuffer()");
    } else {
        runtest.fail("initTestBuffer()");
    }
#endif
    
    /// @coords an array of 16-bit signed integer coordinates. Even indices
    ///         (and 0) are x coordinates, while uneven ones are y coordinates.
    /// @vertex_count the number of x-y coordinates (vertices).
    /// @color the color to be used to draw the line strip.
    /// @mat the SWFMatrix to be used to transform the vertices.
    boost::uint16_t x = 10;
    boost::uint16_t y = 10;
    boost::uint16_t h = 10;
    std::vector<point> box = boost::assign::list_of
        (point(x, y))
        (point(x, y + h));

    rgba color(0, 0, 0, 255);
    SWFMatrix mat;
    mat.set_scale_rotation(1, 3, 0);

    Timer tdrawline("drawline");
    renderer->drawLine(box, color, mat);
    tdrawline.stop();
    
    // if (1) {
    //     runtest.pass("drawLine()");
    // } else {
    //     runtest.fail("drawLine()");
    // }
    runtest.unresolved(std::string("drawLine() ") + tdrawline.elapsed());

    //drawVideoFrame(image::GnashImage* frame, const Transform& xform, const SWFRect* bounds, bool smooth);
#if 0
    image::GnashImage *frame;
    const Transform xform;
    const SWFRect bounds;
    bool smooth;
    Timer tdrawvideo("drawVideoFrame");
    renderer->drawVideoFrame(frame, xform, bounds, smooth);
    tdrawvideo.stop();
#endif
    runtest.untested("drawVideoFrame()");

    point *corners = 0;
    size_t corner_count = 0;
    rgba fill(0, 0, 0, 255);;
    rgba outline(0, 0, 0, 255);;
    bool masked = true;
    Timer tdrawpoly("drawPoly");
    renderer->draw_poly(corners, corner_count, fill, outline, mat, masked);
    tdrawpoly.stop();
    runtest.unresolved(std::string("drawPoly() ") + tdrawpoly.elapsed());
    
//    SWF::ShapeRecord shape;
    SWFMatrix mat2(0x10000, 0x0, 0x0, 0x10000, 0x0, 0x0);
    SWFCxForm cxform;
    //(0x100, 0x100, 0x100, 0x100, 0x0, 0x0, 0x0, 0x0);
    Transform xform(mat2, cxform);
    SWF::ShapeRecord shape;
    // _bounds = {0x80000000, 0x7fffffff,
    //            0x80000000, 0x80000000,
    //            0x80000000, 0x80000000}}
    Timer drawshape("drawShape");
    renderer->drawShape(shape, xform);
    runtest.unresolved("drawShape()");
    drawshape.stop();
    
//    SWF::ShapeRecord rec;
    // rgba color;
    // SWFMatrix mat;
//    Timer drawGlyph("drawGlyph");
//    renderer->drawGlyph(rec, color, mat);
    runtest.untested("drawGlyph()");
//   drawglyph.stop();

#if 0
    boost::shared_ptr<IOChannel> io;
    FileType ftype;
    Timer renderi("renderToImage");
    renderer->renderToImage(io, ftype);
    renderi.stop();
#endif
    runtest.untested("renderToImage()");

    CachedBitmap *bitmap = 0;
    image::GnashImage *frame2 = new image::ImageRGBA(10, 10);
    std::auto_ptr<image::GnashImage> im(frame2);
    Timer cbit("createCachedBitmap");
    bitmap = renderer->createCachedBitmap(im);
    cbit.stop();
    if (bitmap) {
        runtest.pass(std::string("createCachedBitmap() ") + cbit.elapsed());
    } else {
        runtest.fail(std::string("createCachedBitmap() ") + cbit.elapsed());
    }
    
}
Exemplo n.º 7
0
int
main(int /*argc*/, char** /*argv*/)
{
    // 
    // Test boost types, SWFMatrix design is rely on this.
    // 
    // Note: If any of the following tests fails, your boost library
    // is bogus or hasn't been installed properly.
    // 
    check_equals(sizeof(boost::int8_t),   1);
    check_equals(sizeof(boost::uint8_t),  1);
    check_equals(sizeof(boost::int16_t),  2);
    check_equals(sizeof(boost::uint16_t), 2);
    check_equals(sizeof(boost::int32_t),  4);
    check_equals(sizeof(boost::uint32_t), 4);
    check_equals(sizeof(boost::int64_t),  8);
    check_equals(sizeof(boost::uint64_t), 8);

    // 
    //  Test identity SWFMatrix.
    // 
    SWFMatrix identity; 
    check(identity.is_valid());
    check_equals(identity.get_x_scale(), 1);
    check_equals(identity.get_y_scale(), 1);
    check_equals(identity.get_rotation(), 0);
    check_equals(identity.get_x_translation(), 0);
    check_equals(identity.get_y_translation(), 0);

    check_equals(identity.invert(), identity);

    //
    // Test parameter setting and getting, interfaces for AS.
    //
    SWFMatrix m1;
    m1.set_scale_rotation(1, 3, 0);
    check_equals(m1.get_x_scale(), 1);
    check_equals(m1.get_y_scale(), 3);
    check_equals(m1.get_rotation(), 0);
    check_equals(m1.get_x_translation(), 0);
    check_equals(m1.get_y_translation(), 0);

    m1.set_scale(1.5, 2.5);
    check_equals(D(m1.get_x_scale()), 1.5);
    check_equals(D(m1.get_y_scale()), 2.5);
    check_equals(D(m1.get_rotation()), 0);
    check_equals(m1.get_x_translation(), 0);
    check_equals(m1.get_y_translation(), 0);

    m1.set_scale(34, 4);
    check_equals(D(m1.get_x_scale()), 34);
    check_equals(D(m1.get_y_scale()), 4);
    check_equals(D(m1.get_rotation()), 0);
    check_equals(m1.get_x_translation(), 0);
    check_equals(m1.get_y_translation(), 0);

    m1.set_scale_rotation(1, 1, 2);
    check_equals(D(m1.get_x_scale()), 1);
    check_equals(D(m1.get_y_scale()), 1);
    check_equals(D(m1.get_rotation()), 2);
    check_equals(m1.get_x_translation(), 0);
    check_equals(m1.get_y_translation(), 0);

    m1.set_x_scale(2);
    check_equals(D(m1.get_x_scale()), 2);
    check_equals(D(m1.get_y_scale()), 1);
    check_equals(D(m1.get_rotation()), 2);
    check_equals(m1.get_x_translation(), 0);
    check_equals(m1.get_y_translation(), 0);

    m1.set_scale(1, 2);
    check_equals(D(m1.get_x_scale()), 1);
    check_equals(D(m1.get_y_scale()), 2);
    check_equals(D(m1.get_rotation()), 2);
    check_equals(m1.get_x_translation(), 0);
    check_equals(m1.get_y_translation(), 0);

    m1.set_rotation(0);
    check_equals(D(m1.get_x_scale()), 1);
    check_equals(D(m1.get_y_scale()), 2);
    check_equals(D(m1.get_rotation()), 0);
    check_equals(m1.get_x_translation(), 0);
    check_equals(m1.get_y_translation(), 0);

    m1.set_translation(5, 6);
    check_equals(D(m1.get_x_scale()), 1);
    check_equals(D(m1.get_y_scale()), 2);
    check_equals(D(m1.get_rotation()), 0);
    check_equals(m1.get_x_translation(), 5);
    check_equals(m1.get_y_translation(), 6);

    m1.set_rotation(2);
    check_equals(D(m1.get_x_scale()), 1);
    check_equals(D(m1.get_y_scale()), 2);
    check_equals(D(m1.get_rotation()), 2);
    check_equals(m1.get_x_translation(), 5);
    check_equals(m1.get_y_translation(), 6);

    SWFMatrix m2;
    check_equals(D(m2.get_rotation()), 0);
    m2.set_x_scale(16);
    check_equals(D(m2.get_x_scale()), 16);
    check_equals(D(m2.get_y_scale()), 1);
    check_equals(D(m2.get_rotation()), 0);
    m2.set_x_scale(-16);
    check_equals(D(m2.get_x_scale()), 16);
    check_equals(D(m2.get_y_scale()), 1);
    check_equals(D(m2.get_rotation()), 3.14159);
    m2.set_x_scale(16);
    check_equals(D(m2.get_x_scale()), 16);
    check_equals(D(m2.get_y_scale()), 1);
    check_equals(D(m2.get_rotation()), 3.14159);
    m2.set_x_scale(16);
    m2.set_y_scale(-64);
    check_equals(D(m2.get_x_scale()), 16);
    check_equals(D(m2.get_y_scale()), 64);
    check_equals(D(m2.get_rotation()), 3.14159);
    m2.set_x_scale(16);
    m2.set_x_scale(-128);
    check_equals(D(m2.get_x_scale()), 128);
    check_equals(D(m2.get_y_scale()), 64);
    check_equals(D(m2.get_rotation()), 0);

    //
    // Test SWFMatrix concatenation
    //
    m1.concatenate_scale(2, 2);
    check_equals(D(m1.get_x_scale()), 2);
    check_equals(D(m1.get_y_scale()), 4);
    check_equals(D(m1.get_rotation()), 2);
    check_equals(m1.get_x_translation(), 5);
    check_equals(m1.get_y_translation(), 6);

    m1.concatenate_scale(3, 3);
    check_equals(D(m1.get_x_scale()), 6);
    check_equals(D(m1.get_y_scale()), 12);
    check_equals(D(m1.get_rotation()), 2);
    check_equals(m1.get_x_translation(), 5);
    check_equals(m1.get_y_translation(), 6);

    m1.concatenate_scale(2, 1);
    check_equals(D(m1.get_x_scale()), 12);
    check_equals(D(m1.get_y_scale()), 12);
    check_equals(D(m1.get_rotation()), 2);
    check_equals(m1.get_x_translation(), 5);
    check_equals(m1.get_y_translation(), 6);

    //
    // Test SWFMatrix transformations
    //
    point p1(0, 0);
    point p2(64, 64);
    point r;

    m1.set_identity();
    // Make a distance of 64 become a distance of 20 .. 
    m1.set_scale(20.0/64, 20.0/64);

    m1.transform(&r, p1);
    check_equals(r.x, 0);
    check_equals(r.y, 0);
   
    m1.transform(&r, p2);
    check_equals(r.x, 20);
    check_equals(r.y, 20);

    // Translate points to have the origin at 32,32
    // (coordinates expressed in prior-to-scaling SWFMatrix)
    m1.concatenate_translation(-32, -32);

    m1.transform(&r, p1);
    check_equals(r.x, -10);
    check_equals(r.y, -10);

    m1.transform(&r, p2);
    check_equals(r.x, 10);
    check_equals(r.y, 10);

    //  Apply a final scaling by 10 keeping the current origin 
    // (reached after translation)
    SWFMatrix final;
    final.set_scale(10, 10);