Ejemplo n.º 1
0
void SE_Renderer::DrawSymbol(SE_RenderPrimitiveList& symbol,
                             const SE_Matrix& xform,
                             double angleRad,
                             bool excludeRegion)
{
    RS_Bounds extents(DBL_MAX, DBL_MAX, DBL_MAX, -DBL_MAX, -DBL_MAX, -DBL_MAX);
    unsigned int nprims = symbol.size();

    for (unsigned int i=0; i<nprims; ++i)
    {
        SE_RenderPrimitive* primitive = symbol[i];

        if (primitive->type == SE_RenderPrimitive_Polygon || primitive->type == SE_RenderPrimitive_Polyline)
        {
            SE_RenderPolyline* rp = (SE_RenderPolyline*)primitive;

            LineBuffer* lb = rp->geometry->xf_buffer();

            // update the extents with this primitive
            RS_Bounds lbnds;
            lb->ComputeBounds(lbnds);
            extents.add_bounds(lbnds);

            if (m_bSelectionMode)
            {
                if (primitive->type == SE_RenderPrimitive_Polygon)
                    DrawScreenPolygon(lb, &xform, m_selFillColor);

                m_selLineStroke.cap        = rp->lineStroke.cap;
                m_selLineStroke.join       = rp->lineStroke.join;
                m_selLineStroke.miterLimit = rp->lineStroke.miterLimit;
                DrawScreenPolyline(lb, &xform, m_selLineStroke);
            }
            else
            {
                if (primitive->type == SE_RenderPrimitive_Polygon)
                    DrawScreenPolygon(lb, &xform, ((SE_RenderPolygon*)primitive)->fill);

                DrawScreenPolyline(lb, &xform, rp->lineStroke);
            }
        }
        else if (primitive->type == SE_RenderPrimitive_Text)
        {
            SE_RenderText* tp = (SE_RenderText*)primitive;

            // update the extents with this primitive's bounds
            for (int j=0; j<4; ++j)
                extents.add_point(primitive->bounds[j]);

            // get position and angle to use
            double x, y;
            xform.transform(tp->position[0], tp->position[1], x, y);
            RS_TextDef tdef = tp->tdef;
            tdef.rotation() += angleRad * M_180PI;

            if (m_bSelectionMode)
            {
                tdef.textcolor()   = m_textForeColor;
                tdef.ghostcolor()  = m_textBackColor;
//              tdef.framecolor()  = m_textBackColor;
//              tdef.opaquecolor() = m_textBackColor;
            }

            // Here we cannot use the cached RS_TextMetrics in the SE_RenderText object.
            // We must recalculate the text metrics with the new tdef before we can call DrawScreenText.
            RS_TextMetrics tm;
            if (this->GetRSFontEngine()->GetTextMetrics(tp->content, tdef, tm, false))
                DrawScreenText(tm, tdef, x, y, NULL, 0, 0.0);
        }
        else if (primitive->type == SE_RenderPrimitive_Raster)
        {
            SE_RenderRaster* rp = (SE_RenderRaster*)primitive;

            if (m_bSelectionMode)
            {
                // if the raster symbol is selected, then draw the mask selection polygon only
                LineBuffer *lb = LineBufferPool::NewLineBuffer(m_pPool, 5);
                std::auto_ptr<LineBuffer> spLB(lb);

                lb->MoveTo(rp->bounds[3].x, rp->bounds[3].y);
                for (int i = 0; i < 4; ++i)
                {
                    lb->LineTo(rp->bounds[i].x, rp->bounds[i].y);
                }
                
                DrawScreenPolygon(lb, &xform, m_selFillColor);
                DrawScreenPolyline(lb, &xform, m_selLineStroke);

                LineBufferPool::FreeLineBuffer(m_pPool, spLB.release());
            }
            else 
            {
                ImageData& imgData = rp->imageData;
                if (imgData.data != NULL)
                {
                    // update the extents with this primitive's bounds
                    for (int j=0; j<4; ++j)
                        extents.add_point(primitive->bounds[j]);

                    // get position and angle to use
                    double x, y;
                    xform.transform(rp->position[0], rp->position[1], x, y);
                    double angleDeg = (rp->angleRad + angleRad) * M_180PI;

                    DrawScreenRaster(imgData.data, imgData.size, imgData.format, imgData.width, imgData.height, x, y, rp->extent[0], rp->extent[1], angleDeg, rp->opacity);
                }
            }
        }
    }

    if (nprims > 0)
    {
        // always compute the last symbol extent
        xform.transform(extents.minx, extents.miny, m_lastSymbolExtent[0].x, m_lastSymbolExtent[0].y);
        xform.transform(extents.maxx, extents.miny, m_lastSymbolExtent[1].x, m_lastSymbolExtent[1].y);
        xform.transform(extents.maxx, extents.maxy, m_lastSymbolExtent[2].x, m_lastSymbolExtent[2].y);
        xform.transform(extents.minx, extents.maxy, m_lastSymbolExtent[3].x, m_lastSymbolExtent[3].y);

        if (excludeRegion)
            AddExclusionRegion(m_lastSymbolExtent, 4);
    }
    else
    {
        // symbol contains no primitives - update last symbol extent assuming
        // zero symbol extent, but don't add any exclusion region
        xform.transform(0.0, 0.0, m_lastSymbolExtent[0].x, m_lastSymbolExtent[0].y);
        m_lastSymbolExtent[1].x = m_lastSymbolExtent[2].x = m_lastSymbolExtent[3].x = m_lastSymbolExtent[0].x;
        m_lastSymbolExtent[1].y = m_lastSymbolExtent[2].y = m_lastSymbolExtent[3].y = m_lastSymbolExtent[0].y;
    }
}
Ejemplo n.º 2
0
///////////////////////////////////////////////////////////////////////////////
// Called when applying an area style on a feature geometry.  Area styles can
// can only be applied to polygon feature geometry types.
void SE_Renderer::ProcessArea(SE_ApplyContext* ctx, SE_RenderAreaStyle* style)
{
    // the feature geometry we're applying the style on...
    LineBuffer* featGeom = ctx->geometry;

    // can't apply an area style to point and linestring geometry types
    switch (featGeom->geom_type())
    {
        case GeometryType_Point:
        case GeometryType_MultiPoint:
        case GeometryType_LineString:
        case GeometryType_MultiLineString:
        case GeometryType_CurveString:
        case GeometryType_MultiCurveString:
            return;
    }

    SE_Matrix w2s;
    GetWorldToScreenTransform(w2s);

    //--------------------------------------------------------------
    // special code to handle simple solid fill styles
    //--------------------------------------------------------------

    if (style->solidFill)
    {
        // just draw it and bail out of the layout function
        SE_RenderPolygon* rp = (SE_RenderPolygon*)style->symbol[0];

        if (m_bSelectionMode)
            DrawScreenPolygon(featGeom, &w2s, m_selFillColor);
        else
            DrawScreenPolygon(featGeom, &w2s, rp->fill);
        return;
    }

    // transform the feature geometry to rendering space
    LineBuffer* xfgeom = LineBufferPool::NewLineBuffer(m_pPool, featGeom->point_count());
    std::auto_ptr<LineBuffer> spLB(xfgeom);
    *xfgeom = *featGeom;

    int size = featGeom->point_count();
    for (int i=0; i<size; ++i)
        w2s.transform(xfgeom->x_coord(i), xfgeom->y_coord(i));

    // recompute the bounds
    RS_Bounds& bounds = const_cast<RS_Bounds&>(xfgeom->bounds());
    bounds.minx = bounds.miny = bounds.minz = +DBL_MAX;
    bounds.maxx = bounds.maxy = bounds.maxz = -DBL_MAX;
    xfgeom->ComputeBounds(bounds);

    // account for any viewport rotation
    SE_AreaPositioning ap(xfgeom, style, GetWorldToScreenRotation());
    double baserot = ap.PatternRotation();

    SE_Matrix xform;
    SE_Matrix xformbase = *ctx->xform;
    xformbase.rotate(baserot);

    for (const Point2D* pos = ap.NextLocation(); pos != NULL; pos = ap.NextLocation())
    {
        xform = xformbase;
        xform.translate(pos->x, pos->y);
        DrawSymbol(style->symbol, xform, baserot, style->addToExclusionRegion);
    }

    LineBufferPool::FreeLineBuffer(m_pPool, spLB.release());
}