//----------------------------------------------------------------------------//
void FrameComponent::renderImage(GeometryBuffer& buffer, const Image* image,
                                 VerticalFormatting vertFmt,
                                 HorizontalFormatting horzFmt,
                                 Rectf& destRect, const ColourRect& colours,
                                 const Rectf* clipper, bool /*clipToDisplay*/) const
{
    uint horzTiles, vertTiles;
    float xpos, ypos;

    Sizef imgSz(image->getRenderedSize());

    // calculate initial x co-ordinate and horizontal tile count according to formatting options
    switch (horzFmt)
    {
        case HF_STRETCHED:
            imgSz.d_width = destRect.getWidth();
            xpos = destRect.left();
            horzTiles = 1;
            break;

        case HF_TILED:
            xpos = destRect.left();
            horzTiles = std::abs(static_cast<int>(
                (destRect.getWidth() + (imgSz.d_width - 1)) / imgSz.d_width));
            break;

        case HF_LEFT_ALIGNED:
            xpos = destRect.left();
            horzTiles = 1;
            break;

        case HF_CENTRE_ALIGNED:
            xpos = destRect.left() + CoordConverter::alignToPixels((destRect.getWidth() - imgSz.d_width) * 0.5f);
            horzTiles = 1;
            break;

        case HF_RIGHT_ALIGNED:
            xpos = destRect.right() - imgSz.d_width;
            horzTiles = 1;
            break;

        default:
            CEGUI_THROW(InvalidRequestException(
                "An unknown HorizontalFormatting value was specified."));
    }

    // calculate initial y co-ordinate and vertical tile count according to formatting options
    switch (vertFmt)
    {
        case VF_STRETCHED:
            imgSz.d_height = destRect.getHeight();
            ypos = destRect.top();
            vertTiles = 1;
            break;

        case VF_TILED:
            ypos = destRect.top();
            vertTiles = std::abs(static_cast<int>(
                (destRect.getHeight() + (imgSz.d_height - 1)) / imgSz.d_height));
            break;

        case VF_TOP_ALIGNED:
            ypos = destRect.top();
            vertTiles = 1;
            break;

        case VF_CENTRE_ALIGNED:
            ypos = destRect.top() + CoordConverter::alignToPixels((destRect.getHeight() - imgSz.d_height) * 0.5f);
            vertTiles = 1;
            break;

        case VF_BOTTOM_ALIGNED:
            ypos = destRect.bottom() - imgSz.d_height;
            vertTiles = 1;
            break;

        default:
            CEGUI_THROW(InvalidRequestException(
                "An unknown VerticalFormatting value was specified."));
    }

    // perform final rendering (actually is now a caching of the images which will be drawn)
    Rectf finalRect;
    Rectf finalClipper;
    const Rectf* clippingRect;
    finalRect.d_min.d_y = ypos;
    finalRect.d_max.d_y = ypos + imgSz.d_height;

    for (uint row = 0; row < vertTiles; ++row)
    {
        finalRect.d_min.d_x = xpos;
        finalRect.d_max.d_x = xpos + imgSz.d_width;

        for (uint col = 0; col < horzTiles; ++col)
        {
            // use custom clipping for right and bottom edges when tiling the imagery
            if (((vertFmt == VF_TILED) && row == vertTiles - 1) ||
                ((horzFmt == HF_TILED) && col == horzTiles - 1))
            {
                finalClipper = clipper ? clipper->getIntersection(destRect) : destRect;
                clippingRect = &finalClipper;
            }
            // not tiliing, or not on far edges, just used passed in clipper (if any).
            else
                clippingRect = clipper;

            image->render(buffer, finalRect, clippingRect, colours);

            finalRect.d_min.d_x += imgSz.d_width;
            finalRect.d_max.d_x += imgSz.d_width;
        }

        finalRect.d_min.d_y += imgSz.d_height;
        finalRect.d_max.d_y += imgSz.d_height;
    }
}
    void ImageryComponent::render_impl(Window& srcWindow, Rect& destRect, float base_z, const CEGUI::ColourRect* modColours, const Rect* clipper, bool clipToDisplay) const
    {
        // get final image to use.
        const Image* img = isImageFetchedFromProperty() ?
            PropertyHelper::stringToImage(srcWindow.getProperty(d_imagePropertyName)) :
            d_image;

        // do not draw anything if image is not set.
        if (!img)
            return;

        HorizontalFormatting horzFormatting = d_horzFormatPropertyName.empty() ? d_horzFormatting :
            FalagardXMLHelper::stringToHorzFormat(srcWindow.getProperty(d_horzFormatPropertyName));

        VerticalFormatting vertFormatting = d_vertFormatPropertyName.empty() ? d_vertFormatting :
            FalagardXMLHelper::stringToVertFormat(srcWindow.getProperty(d_vertFormatPropertyName));

        uint horzTiles, vertTiles;
        float xpos, ypos;

        Size imgSz(img->getSize());

        // calculate final colours to be used
        ColourRect finalColours;
        initColoursRect(srcWindow, modColours, finalColours);

        // calculate initial x co-ordinate and horizontal tile count according to formatting options
        switch (horzFormatting)
        {
            case HF_STRETCHED:
                imgSz.d_width = destRect.getWidth();
                xpos = destRect.d_left;
                horzTiles = 1;
                break;

            case HF_TILED:
                xpos = destRect.d_left;
                horzTiles = (uint)((destRect.getWidth() + (imgSz.d_width - 1)) / imgSz.d_width);
                break;

            case HF_LEFT_ALIGNED:
                xpos = destRect.d_left;
                horzTiles = 1;
                break;

            case HF_CENTRE_ALIGNED:
                xpos = destRect.d_left + PixelAligned((destRect.getWidth() - imgSz.d_width) * 0.5f);
                horzTiles = 1;
                break;

            case HF_RIGHT_ALIGNED:
                xpos = destRect.d_right - imgSz.d_width;
                horzTiles = 1;
                break;

            default:
                throw InvalidRequestException("ImageryComponent::render - An unknown HorizontalFormatting value was specified.");
        }

        // calculate initial y co-ordinate and vertical tile count according to formatting options
        switch (vertFormatting)
        {
            case VF_STRETCHED:
                imgSz.d_height = destRect.getHeight();
                ypos = destRect.d_top;
                vertTiles = 1;
                break;

            case VF_TILED:
                ypos = destRect.d_top;
                vertTiles = (uint)((destRect.getHeight() + (imgSz.d_height - 1)) / imgSz.d_height);
                break;

            case VF_TOP_ALIGNED:
                ypos = destRect.d_top;
                vertTiles = 1;
                break;

            case VF_CENTRE_ALIGNED:
                ypos = destRect.d_top + PixelAligned((destRect.getHeight() - imgSz.d_height) * 0.5f);
                vertTiles = 1;
                break;

            case VF_BOTTOM_ALIGNED:
                ypos = destRect.d_bottom - imgSz.d_height;
                vertTiles = 1;
                break;

            default:
                throw InvalidRequestException("ImageryComponent::render - An unknown VerticalFormatting value was specified.");
        }

        // perform final rendering (actually is now a caching of the images which will be drawn)
        Rect finalRect;
        Rect finalClipper;
        const Rect* clippingRect;
        finalRect.d_top = ypos;
        finalRect.d_bottom = ypos + imgSz.d_height;

        for (uint row = 0; row < vertTiles; ++row)
        {
            finalRect.d_left = xpos;
            finalRect.d_right = xpos + imgSz.d_width;

            for (uint col = 0; col < horzTiles; ++col)
            {
                // use custom clipping for right and bottom edges when tiling the imagery
                if (((vertFormatting == VF_TILED) && row == vertTiles - 1) ||
                    ((horzFormatting == HF_TILED) && col == horzTiles - 1))
                {
                    finalClipper = clipper ? clipper->getIntersection(destRect) : destRect;
                    clippingRect = &finalClipper;
                }
                // not tiliing, or not on far edges, just used passed in clipper (if any).
                else
                {
                    clippingRect = clipper;
                }

                // add image to the rendering cache for the target window.
                srcWindow.getRenderCache().cacheImage(*img, finalRect, base_z, finalColours, clippingRect, clipToDisplay);

                finalRect.d_left += imgSz.d_width;
                finalRect.d_right += imgSz.d_width;
            }

            finalRect.d_top += imgSz.d_height;
            finalRect.d_bottom += imgSz.d_height;
        }
    }
    void FrameComponent::doBackgroundRender(Window& srcWindow, Rect& destRect, const ColourRect& colours, const Rect* clipper, bool /*clipToDisplay*/) const
    {
        HorizontalFormatting horzFormatting = d_horzFormatPropertyName.empty() ? d_horzFormatting :
            FalagardXMLHelper::stringToHorzFormat(srcWindow.getProperty(d_horzFormatPropertyName));

        VerticalFormatting vertFormatting = d_vertFormatPropertyName.empty() ? d_vertFormatting :
            FalagardXMLHelper::stringToVertFormat(srcWindow.getProperty(d_vertFormatPropertyName));

        uint horzTiles, vertTiles;
        float xpos, ypos;

        Size imgSz(d_frameImages[FIC_BACKGROUND]->getSize());

        // calculate initial x co-ordinate and horizontal tile count according to formatting options
        switch (horzFormatting)
        {
            case HF_STRETCHED:
                imgSz.d_width = destRect.getWidth();
                xpos = destRect.d_left;
                horzTiles = 1;
                break;

            case HF_TILED:
                xpos = destRect.d_left;
                horzTiles = std::abs(static_cast<int>(
                    (destRect.getWidth() + (imgSz.d_width - 1)) / imgSz.d_width));
                break;

            case HF_LEFT_ALIGNED:
                xpos = destRect.d_left;
                horzTiles = 1;
                break;

            case HF_CENTRE_ALIGNED:
                xpos = destRect.d_left + PixelAligned((destRect.getWidth() - imgSz.d_width) * 0.5f);
                horzTiles = 1;
                break;

            case HF_RIGHT_ALIGNED:
                xpos = destRect.d_right - imgSz.d_width;
                horzTiles = 1;
                break;

            default:
                CEGUI_THROW(InvalidRequestException("FrameComponent::doBackgroundRender - An unknown HorizontalFormatting value was specified."));
        }

        // calculate initial y co-ordinate and vertical tile count according to formatting options
        switch (vertFormatting)
        {
            case VF_STRETCHED:
                imgSz.d_height = destRect.getHeight();
                ypos = destRect.d_top;
                vertTiles = 1;
                break;

            case VF_TILED:
                ypos = destRect.d_top;
                vertTiles = std::abs(static_cast<int>(
                    (destRect.getHeight() + (imgSz.d_height - 1)) / imgSz.d_height));
                break;

            case VF_TOP_ALIGNED:
                ypos = destRect.d_top;
                vertTiles = 1;
                break;

            case VF_CENTRE_ALIGNED:
                ypos = destRect.d_top + PixelAligned((destRect.getHeight() - imgSz.d_height) * 0.5f);
                vertTiles = 1;
                break;

            case VF_BOTTOM_ALIGNED:
                ypos = destRect.d_bottom - imgSz.d_height;
                vertTiles = 1;
                break;

            default:
                CEGUI_THROW(InvalidRequestException("FrameComponent::doBackgroundRender - An unknown VerticalFormatting value was specified."));
        }

        // perform final rendering (actually is now a caching of the images which will be drawn)
        Rect finalRect;
        Rect finalClipper;
        const Rect* clippingRect;
        finalRect.d_top = ypos;
        finalRect.d_bottom = ypos + imgSz.d_height;

        for (uint row = 0; row < vertTiles; ++row)
        {
            finalRect.d_left = xpos;
            finalRect.d_right = xpos + imgSz.d_width;

            for (uint col = 0; col < horzTiles; ++col)
            {
                // use custom clipping for right and bottom edges when tiling the imagery
                if (((vertFormatting == VF_TILED) && row == vertTiles - 1) ||
                    ((horzFormatting == HF_TILED) && col == horzTiles - 1))
                {
                    finalClipper = clipper ? clipper->getIntersection(destRect) : destRect;
                    clippingRect = &finalClipper;
                }
                // not tiliing, or not on far edges, just used passed in clipper (if any).
                else
                {
                    clippingRect = clipper;
                }

                // add image to the rendering cache for the target window.
                d_frameImages[FIC_BACKGROUND]->draw(srcWindow.getGeometryBuffer(), finalRect, clippingRect, colours);

                finalRect.d_left += imgSz.d_width;
                finalRect.d_right += imgSz.d_width;
            }

            finalRect.d_top += imgSz.d_height;
            finalRect.d_bottom += imgSz.d_height;
        }
    }