void paintComponent()
    {
        // you mustn't set your own cached image object when attaching a GL context!
        jassert (get (component) == this);

        updateViewportSize (false);

        if (! ensureFrameBufferSize())
            return;

        RectangleList invalid (viewportArea);
        invalid.subtract (validArea);
        validArea = viewportArea;

        if (! invalid.isEmpty())
        {
            clearRegionInFrameBuffer (invalid, (float) scale);

            {
                ScopedPointer<LowLevelGraphicsContext> g (createOpenGLGraphicsContext (context, cachedImageFrameBuffer));
                g->addTransform (AffineTransform::scale ((float) scale));
                g->clipToRectangleList (invalid);

                paintOwner (*g);
                JUCE_CHECK_OPENGL_ERROR
            }

            if (! context.isActive())
                context.makeActive();
        }
Exemple #2
0
bool ResizableWindow::restoreWindowStateFromString (const String& s)
{
    StringArray tokens;
    tokens.addTokens (s, false);
    tokens.removeEmptyStrings();
    tokens.trim();

    const bool fs = tokens[0].startsWithIgnoreCase ("fs");
    const int firstCoord = fs ? 1 : 0;

    if (tokens.size() != firstCoord + 4)
        return false;

    Rectangle<int> newPos (tokens[firstCoord].getIntValue(),
                           tokens[firstCoord + 1].getIntValue(),
                           tokens[firstCoord + 2].getIntValue(),
                           tokens[firstCoord + 3].getIntValue());

    if (newPos.isEmpty())
        return false;

    ComponentPeer* const peer = isOnDesktop() ? getPeer() : nullptr;
    if (peer != nullptr)
        peer->getFrameSize().addTo (newPos);

    {
        Desktop& desktop = Desktop::getInstance();
        RectangleList allMonitors (desktop.getDisplays().getRectangleList (true));
        allMonitors.clipTo (newPos);
        const Rectangle<int> onScreenArea (allMonitors.getBounds());

        if (onScreenArea.getWidth() * onScreenArea.getHeight() < 32 * 32)
        {
            const Rectangle<int> screen (desktop.getDisplays().getDisplayContaining (newPos.getCentre()).userArea);

            newPos.setSize (jmin (newPos.getWidth(),  screen.getWidth()),
                            jmin (newPos.getHeight(), screen.getHeight()));

            newPos.setPosition (jlimit (screen.getX(), screen.getRight()  - newPos.getWidth(),  newPos.getX()),
                                jlimit (screen.getY(), screen.getBottom() - newPos.getHeight(), newPos.getY()));
        }
    }

    if (peer != nullptr)
    {
        peer->getFrameSize().subtractFrom (newPos);
        peer->setNonFullScreenBounds (newPos);
    }

    lastNonFullScreenPos = newPos;
    setFullScreen (fs);

    if (! fs)
        setBoundsConstrained (newPos);

    return true;
}
void Graphics::drawRect (Rectangle<float> r, const float lineThickness) const
{
    RectangleList<float> rects;
    rects.addWithoutMerging (r.removeFromTop    (lineThickness));
    rects.addWithoutMerging (r.removeFromBottom (lineThickness));
    rects.addWithoutMerging (r.removeFromLeft   (lineThickness));
    rects.addWithoutMerging (r.removeFromRight  (lineThickness));
    context.fillRectList (rects);
}
Exemple #4
0
void Screen::update() {
	_ticks = _vm->_system->getMillis();
	updatePalette();

	if (_fullRefresh) {
		// NOTE When playing a fullscreen/doubled Smacker video usually a full screen refresh is needed
		_vm->_system->copyRectToScreen((const byte*)_backScreen->getPixels(), _backScreen->pitch, 0, 0, 640, 480);
		_fullRefresh = false;
		return;
	}

	_microTiles->clear();

	for (RenderQueue::iterator it = _renderQueue->begin(); it != _renderQueue->end(); ++it) {
		RenderItem &renderItem = (*it);
		renderItem._refresh = true;
		for (RenderQueue::iterator jt = _prevRenderQueue->begin(); jt != _prevRenderQueue->end(); ++jt) {
			RenderItem &prevRenderItem = (*jt);
			if (prevRenderItem == renderItem) {
				prevRenderItem._refresh = false;
				renderItem._refresh = false;
			}
		}
	}

	for (RenderQueue::iterator jt = _prevRenderQueue->begin(); jt != _prevRenderQueue->end(); ++jt) {
		RenderItem &prevRenderItem = (*jt);
		if (prevRenderItem._refresh)
			_microTiles->addRect(Common::Rect(prevRenderItem._destX, prevRenderItem._destY, prevRenderItem._destX + prevRenderItem._width, prevRenderItem._destY + prevRenderItem._height));
	}

	for (RenderQueue::iterator it = _renderQueue->begin(); it != _renderQueue->end(); ++it) {
		RenderItem &renderItem = (*it);
		if (renderItem._refresh)
			_microTiles->addRect(Common::Rect(renderItem._destX, renderItem._destY, renderItem._destX + renderItem._width, renderItem._destY + renderItem._height));
		renderItem._refresh = true;
	}

	RectangleList *updateRects = _microTiles->getRectangles();

	for (RenderQueue::iterator it = _renderQueue->begin(); it != _renderQueue->end(); ++it) {
		RenderItem &renderItem = (*it);
		for (RectangleList::iterator ri = updateRects->begin(); ri != updateRects->end(); ++ri)
			blitRenderItem(renderItem, *ri);
	}

	SWAP(_renderQueue, _prevRenderQueue);
	_renderQueue->clear();

	for (RectangleList::iterator ri = updateRects->begin(); ri != updateRects->end(); ++ri) {
		Common::Rect &r = *ri;
		_vm->_system->copyRectToScreen((const byte*)_backScreen->getBasePtr(r.left, r.top), _backScreen->pitch, r.left, r.top, r.width(), r.height());
	}

	delete updateRects;

}
const RectangleList Desktop::getAllMonitorDisplayAreas (const bool clippedToWorkArea) const throw()
{
    RectangleList rl;

    for (int i = 0; i < getNumDisplayMonitors(); ++i)
        rl.addWithoutMerging (getDisplayMonitorCoordinates (i, clippedToWorkArea));

    return rl;
}
Exemple #6
0
RectangleList<int> Displays::getRectangleList (bool userAreasOnly) const
{
    ASSERT_MESSAGE_MANAGER_IS_LOCKED
    RectangleList<int> rl;

    for (auto& d : displays)
        rl.addWithoutMerging (userAreasOnly ? d.userArea : d.totalArea);

    return rl;
}
void Graphics::drawRect (Rectangle<float> r, const float lineThickness) const
{
    jassert (r.getWidth() >= 0.0f && r.getHeight() >= 0.0f);

    RectangleList<float> rects;
    rects.addWithoutMerging (r.removeFromTop    (lineThickness));
    rects.addWithoutMerging (r.removeFromBottom (lineThickness));
    rects.addWithoutMerging (r.removeFromLeft   (lineThickness));
    rects.addWithoutMerging (r.removeFromRight  (lineThickness));
    context.fillRectList (rects);
}
//==============================================================================
void RectangleList::add (const Rectangle<int>& rect)
{
    if (! rect.isEmpty())
    {
        if (rects.size() == 0)
        {
            rects.add (rect);
        }
        else
        {
            bool anyOverlaps = false;

            int i;
            for (i = rects.size(); --i >= 0;)
            {
                Rectangle<int>& ourRect = rects.getReference (i);

                if (rect.intersects (ourRect))
                {
                    if (rect.contains (ourRect))
                        rects.remove (i);
                    else if (! ourRect.reduceIfPartlyContainedIn (rect))
                        anyOverlaps = true;
                }
            }

            if (anyOverlaps && rects.size() > 0)
            {
                RectangleList r (rect);

                for (i = rects.size(); --i >= 0;)
                {
                    const Rectangle<int>& ourRect = rects.getReference (i);

                    if (rect.intersects (ourRect))
                    {
                        r.subtract (ourRect);

                        if (r.rects.size() == 0)
                            return;
                    }
                }

                for (i = r.getNumRectangles(); --i >= 0;)
                    rects.add (r.rects.getReference (i));
            }
            else
            {
                rects.add (rect);
            }
        }
    }
}
RectangleList Desktop::Displays::getRectangleList (bool userAreasOnly) const
{
    RectangleList rl;

    for (int i = 0; i < displays.size(); ++i)
    {
        const Display& d = displays.getReference(i);
        rl.addWithoutMerging (userAreasOnly ? d.userArea : d.totalArea);
    }

    return rl;
}
void drawMouseOverCorners (Graphics& g, int w, int h)
{
    RectangleList r (Rectangle<int> (0, 0, w, h));
    r.subtract (Rectangle<int> (1, 1, w - 2, h - 2));

    const int size = jmin (w / 3, h / 3, 12);
    r.subtract (Rectangle<int> (size, 0, w - size - size, h));
    r.subtract (Rectangle<int> (0, size, w, h - size - size));

    g.setColour (Colours::darkgrey);

    for (int i = r.getNumRectangles(); --i >= 0;)
        g.fillRect (r.getRectangle (i));
}
Exemple #11
0
RectangleList *MicroTileArray::getRectangles() {

	RectangleList *rects = new RectangleList();

	int x, y;
	int x0, y0, x1, y1;
	int i = 0;

	for (y = 0; y < _tilesH; ++y) {
		for (x = 0; x < _tilesW; ++x) {

			int finish = 0;
			BoundingBox boundingBox = _tiles[i];

			if (isBoundingBoxEmpty(boundingBox)) {
				++i;
				continue;
			}

			x0 = (x * TileSize) + TileX0(boundingBox);
			y0 = (y * TileSize) + TileY0(boundingBox);
			y1 = (y * TileSize) + TileY1(boundingBox);

			if (TileX1(boundingBox) == TileSize - 1 && x != _tilesW - 1) {	// check if the tile continues
				while (!finish) {
					++x;
					++i;
					if (x == _tilesW || i >= _tilesW * _tilesH ||
						TileY0(_tiles[i]) != TileY0(boundingBox) ||
						TileY1(_tiles[i]) != TileY1(boundingBox) ||
						TileX0(_tiles[i]) != 0)
					{
						--x;
						--i;
						finish = 1;
					}
				}
			}

			x1 = (x * TileSize) + TileX1(_tiles[i]);

			rects->push_back(Common::Rect(x0, y0, x1 + 1, y1 + 1));

			++i;
		}
	}

	return rects;
}
Exemple #12
0
void Image::createSolidAreaMask (RectangleList& result, const float alphaThreshold) const
{
    if (hasAlphaChannel())
    {
        const uint8 threshold = (uint8) jlimit (0, 255, roundToInt (alphaThreshold * 255.0f));
        SparseSet<int> pixelsOnRow;

        const BitmapData srcData (*this, 0, 0, getWidth(), getHeight());

        for (int y = 0; y < srcData.height; ++y)
        {
            pixelsOnRow.clear();
            const uint8* lineData = srcData.getLinePointer (y);

            if (isARGB())
            {
                for (int x = 0; x < srcData.width; ++x)
                {
                    if (((const PixelARGB*) lineData)->getAlpha() >= threshold)
                        pixelsOnRow.addRange (Range<int> (x, x + 1));

                    lineData += srcData.pixelStride;
                }
            }
            else
            {
                for (int x = 0; x < srcData.width; ++x)
                {
                    if (*lineData >= threshold)
                        pixelsOnRow.addRange (Range<int> (x, x + 1));

                    lineData += srcData.pixelStride;
                }
            }

            for (int i = 0; i < pixelsOnRow.getNumRanges(); ++i)
            {
                const Range<int> range (pixelsOnRow.getRange (i));
                result.add (Rectangle<int> (range.getStart(), y, range.getLength(), 1));
            }

            result.consolidate();
        }
    }
    else
    {
        result.add (0, 0, getWidth(), getHeight());
    }
}
Exemple #13
0
    void drawDemo (Graphics& g) override
    {
        {
            RectangleList<float> verticalLines;
            float pos = offset.getValue();

            for (int x = 0; x < getWidth(); ++x)
            {
                float y = getHeight() * 0.3f;
                float length = y * std::abs (std::sin (x / 100.0f + 2.0f * pos));
                verticalLines.addWithoutMerging (Rectangle<float> ((float) x, y - length * 0.5f, 1.0f, length));
            }

            g.setColour (Colours::blue.withAlpha (getAlpha()));
            g.fillRectList (verticalLines);
        }

        {
            RectangleList<float> horizontalLines;
            float pos = offset.getValue();

            for (int y = 0; y < getHeight(); ++y)
            {
                float x = getWidth() * 0.3f;
                float length = x * std::abs (std::sin (y / 100.0f + 2.0f * pos));
                horizontalLines.addWithoutMerging (Rectangle<float> (x - length * 0.5f, (float) y, length, 1.0f));
            }

            g.setColour (Colours::green.withAlpha (getAlpha()));
            g.fillRectList (horizontalLines);
        }

        g.setColour (Colours::red.withAlpha (getAlpha()));

        const float w = (float) getWidth();
        const float h = (float) getHeight();

        g.drawLine (positions[0].getValue() * w,
                    positions[1].getValue() * h,
                    positions[2].getValue() * w,
                    positions[3].getValue() * h);

        g.drawLine (positions[4].getValue() * w,
                    positions[5].getValue() * h,
                    positions[6].getValue() * w,
                    positions[7].getValue() * h);
    }
bool RectangleList::intersects (const RectangleList& other) const noexcept
{
    for (int i = rects.size(); --i >= 0;)
        if (other.intersectsRectangle (rects.getReference (i)))
            return true;

    return false;
}
void Graphics::fillCheckerBoard (Rectangle<float> area, float checkWidth, float checkHeight,
                                 Colour colour1, Colour colour2) const
{
    jassert (checkWidth > 0 && checkHeight > 0); // can't be zero or less!

    if (checkWidth > 0 && checkHeight > 0)
    {
        context.saveState();

        if (colour1 == colour2)
        {
            context.setFill (colour1);
            context.fillRect (area);
        }
        else
        {
            auto clipped = context.getClipBounds().getIntersection (area.getSmallestIntegerContainer());

            if (! clipped.isEmpty())
            {
                const int checkNumX = (int) ((clipped.getX() - area.getX()) / checkWidth);
                const int checkNumY = (int) ((clipped.getY() - area.getY()) / checkHeight);
                const float startX = area.getX() + checkNumX * checkWidth;
                const float startY = area.getY() + checkNumY * checkHeight;
                const float right  = (float) clipped.getRight();
                const float bottom = (float) clipped.getBottom();

                for (int i = 0; i < 2; ++i)
                {
                    int cy = i;
                    RectangleList<float> checks;

                    for (float y = startY; y < bottom; y += checkHeight)
                        for (float x = startX + (cy++ & 1) * checkWidth; x < right; x += checkWidth * 2.0f)
                            checks.addWithoutMerging ({ x, y, checkWidth, checkHeight });

                    checks.clipTo (area);
                    context.setFill (i == ((checkNumX ^ checkNumY) & 1) ? colour1 : colour2);
                    context.fillRectList (checks);
                }
            }
        }

        context.restoreState();
    }
}
Exemple #16
0
void LiveAudioInputDisplayComp::paint (Graphics& g)
{
    RectangleList<float> waveform;

    const float midY = getHeight() * 0.5f;
    int sampleNum = (nextSample + numElementsInArray (samples) - 1);

    for (int x = jmin (getWidth(), (int) numElementsInArray (samples)); --x >= 0;)
    {
        const float sampleSize = midY * samples [sampleNum-- % numElementsInArray (samples)];
        waveform.addWithoutMerging (Rectangle<float> ((float) x, midY - sampleSize, 1.0f, sampleSize * 2.0f));
    }

    g.fillAll (Colours::black);

    g.setColour (Colours::green);
    g.fillRectList (waveform);
}
Exemple #17
0
    void drawChannel (Graphics& g, const Rectangle<int>& area,
                      const double startTime, const double endTime,
                      const int channelNum, const float verticalZoomFactor,
                      const double rate, const int numChans, const int sampsPerThumbSample,
                      LevelDataSource* levelData, const OwnedArray<ThumbData>& chans)
    {
        if (refillCache (area.getWidth(), startTime, endTime, rate,
                         numChans, sampsPerThumbSample, levelData, chans)
             && isPositiveAndBelow (channelNum, numChannelsCached))
        {
            const Rectangle<int> clip (g.getClipBounds().getIntersection (area.withWidth (jmin (numSamplesCached, area.getWidth()))));

            if (! clip.isEmpty())
            {
                const float topY = (float) area.getY();
                const float bottomY = (float) area.getBottom();
                const float midY = (topY + bottomY) * 0.5f;
                const float vscale = verticalZoomFactor * (bottomY - topY) / 256.0f;

                const MinMaxValue* cacheData = getData (channelNum, clip.getX() - area.getX());

                RectangleList<float> waveform;
                waveform.ensureStorageAllocated (clip.getWidth());

                float x = (float) clip.getX();

                for (int w = clip.getWidth(); --w >= 0;)
                {
                    if (cacheData->isNonZero())
                    {
                        const float top    = jmax (midY - cacheData->getMaxValue() * vscale - 0.3f, topY);
                        const float bottom = jmin (midY - cacheData->getMinValue() * vscale + 0.3f, bottomY);

                        waveform.addWithoutMerging (Rectangle<float> (x, top, 1.0f, bottom - top));
                    }

                    x += 1.0f;
                    ++cacheData;
                }

                g.fillRectList (waveform);
            }
        }
    }
    void drawCurrentImage (Graphics& g, Rectangle<int> area)
    {
        if (imageNeedsFlipping)
        {
            const ScopedLock sl (imageSwapLock);
            std::swap (loadingImage, activeImage);
            imageNeedsFlipping = false;
        }

        Rectangle<int> centred (RectanglePlacement (RectanglePlacement::centred)
                                    .appliedTo (Rectangle<int> (width, height), area));

        RectangleList<int> borders (area);
        borders.subtract (centred);
        g.setColour (Colours::black);
        g.fillRectList (borders);

        g.drawImage (activeImage, centred.getX(), centred.getY(),
                     centred.getWidth(), centred.getHeight(), 0, 0, width, height);
    }
    void clearRegionInFrameBuffer (const RectangleList& list, const float scaleFactor)
    {
        glClearColor (0, 0, 0, 0);
        glEnable (GL_SCISSOR_TEST);

        const GLuint previousFrameBufferTarget = OpenGLFrameBuffer::getCurrentFrameBufferTarget();
        cachedImageFrameBuffer.makeCurrentRenderingTarget();
        const int imageH = cachedImageFrameBuffer.getHeight();

        for (const Rectangle<int>* i = list.begin(), * const e = list.end(); i != e; ++i)
        {
            const Rectangle<int> r ((i->toFloat() * scaleFactor).getSmallestIntegerContainer());
            glScissor (r.getX(), imageH - r.getBottom(), r.getWidth(), r.getHeight());
            glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        }

        glDisable (GL_SCISSOR_TEST);
        context.extensions.glBindFramebuffer (GL_FRAMEBUFFER, previousFrameBufferTarget);
        JUCE_CHECK_OPENGL_ERROR
    }
void TabbedComponent::paint (Graphics& g)
{
    g.fillAll (findColour (backgroundColourId));

    Rectangle<int> content (getLocalBounds());
    BorderSize<int> outline (outlineThickness);
    TabbedComponentHelpers::getTabArea (content, outline, getOrientation(), tabDepth);

    g.reduceClipRegion (content);
    g.fillAll (tabs->getTabBackgroundColour (getCurrentTabIndex()));

    if (outlineThickness > 0)
    {
        RectangleList rl (content);
        rl.subtract (outline.subtractedFrom (content));

        g.reduceClipRegion (rl);
        g.fillAll (findColour (outlineColourId));
    }
}
bool RectangleList::containsRectangle (const Rectangle<int>& rectangleToCheck) const
{
    if (rects.size() > 1)
    {
        RectangleList r (rectangleToCheck);

        for (int i = rects.size(); --i >= 0;)
        {
            r.subtract (rects.getReference (i));

            if (r.rects.size() == 0)
                return true;
        }
    }
    else if (rects.size() > 0)
    {
        return rects.getReference (0).contains (rectangleToCheck);
    }

    return false;
}
void LowLevelGraphicsPostScriptRenderer::drawImage (const Image& sourceImage, const AffineTransform& transform)
{
    const int w = sourceImage.getWidth();
    const int h = sourceImage.getHeight();

    writeClip();

    out << "gsave ";
    writeTransform (transform.translated ((float) stateStack.getLast()->xOffset, (float) stateStack.getLast()->yOffset)
                             .scaled (1.0f, -1.0f));

    RectangleList<int> imageClip;
    sourceImage.createSolidAreaMask (imageClip, 0.5f);

    out << "newpath ";
    int itemsOnLine = 0;

    for (const Rectangle<int>* i = imageClip.begin(), * const e = imageClip.end(); i != e; ++i)
    {
        if (++itemsOnLine == 6)
        {
            out << '\n';
            itemsOnLine = 0;
        }

        out << i->getX() << ' ' << i->getY() << ' ' << i->getWidth() << ' ' << i->getHeight() << " pr ";
    }

    out << " clip newpath\n";

    out << w << ' ' << h << " scale\n";
    out << w << ' ' << h << " 8 [" << w << " 0 0 -" << h << ' ' << (int) 0 << ' ' << h << " ]\n";

    writeImage (sourceImage, 0, 0, w, h);

    out << "false 3 colorimage grestore\n";
    needToClip = true;
}
    void paintComponent()
    {
        if (needsUpdate)
        {
            MessageManagerLock mm (this);
            if (! mm.lockWasGained())
                return;

            needsUpdate = false;

            // you mustn't set your own cached image object when attaching a GL context!
            jassert (get (component) == this);

            const Rectangle<int> bounds (component.getLocalBounds());
            if (! ensureFrameBufferSize (bounds.getWidth(), bounds.getHeight()))
                return;

            RectangleList invalid (bounds);
            invalid.subtract (validArea);
            validArea = bounds;

            if (! invalid.isEmpty())
            {
                clearRegionInFrameBuffer (invalid);

                {
                    ScopedPointer<LowLevelGraphicsContext> g (createOpenGLGraphicsContext (context, cachedImageFrameBuffer));
                    g->clipToRectangleList (invalid);
                    paintOwner (*g);
                    JUCE_CHECK_OPENGL_ERROR
                }

                if (! context.isActive())
                    context.makeActive();
            }

            JUCE_CHECK_OPENGL_ERROR
        }
void CtrlrCustomButtonInternal::drawTextBoxText(Graphics &g, const Rectangle<int> &frameRect, const Rectangle<int> &totalAreaToDraw)
{
	RectangleList<int> list;
	list.add (totalAreaToDraw);
	list.subtract (frameRect);
	Rectangle<int> destination = list.getBounds();

	const int destinationWidth = (int)owner.getProperty(::Ids::uiImageButtonTextWidth)  ? (int)owner.getProperty(::Ids::uiImageButtonTextWidth)  : destination.getWidth();
	const int destinatioHeight = (int)owner.getProperty(::Ids::uiImageButtonTextHeight) ? (int)owner.getProperty(::Ids::uiImageButtonTextHeight) : destination.getHeight();

	destination.setSize (destinationWidth, destinatioHeight);

	g.setColour (VAR2COLOUR(owner.getProperty(::Ids::uiImageButtonTextColour)));
	g.setFont (owner.getOwner().getOwnerPanel().getCtrlrManagerOwner().getFontManager().getFontFromString(owner.getProperty(::Ids::uiButtonTextFont)));

	g.drawFittedText (getButtonText(),
							destination.getX(),
							destination.getY(),
							destination.getWidth(),
							destination.getHeight(),
							justificationFromProperty (owner.getProperty(::Ids::uiButtonTextJustification)),
							2);
}
bool RectangleList::getIntersectionWith (const Rectangle<int>& rect, RectangleList& destRegion) const
{
    destRegion.clear();

    if (! rect.isEmpty())
    {
        for (int i = rects.size(); --i >= 0;)
        {
            Rectangle<int> r (rects.getReference (i));

            if (rect.intersectRectangle (r.x, r.y, r.w, r.h))
                destRegion.rects.add (r);
        }
    }

    return destRegion.rects.size() > 0;
}
 void getHighlightArea (RectangleList<float>& area, float x, int y, int lineH, float characterWidth) const
 {
     if (highlightColumnStart < highlightColumnEnd)
         area.addWithoutMerging (Rectangle<float> (x + highlightColumnStart * characterWidth, (float) y,
                                                   (highlightColumnEnd - highlightColumnStart) * characterWidth, (float) lineH));
 }
bool RenderObjectManager::render() {
	// Den Objekt-Status des Wurzelobjektes aktualisieren. Dadurch werden rekursiv alle Baumelemente aktualisiert.
	// Beim aktualisieren des Objekt-Status werden auch die Update-Rects gefunden, so dass feststeht, was neu gezeichnet
	// werden muss.
	if (!_rootPtr.isValid() || !_rootPtr->updateObjectState())
		return false;

	_frameStarted = false;

	// Die Render-Methode der Wurzel aufrufen. Dadurch wird das rekursive Rendern der Baumelemente angestoßen.

	_currQueue->clear();
	_rootPtr->preRender(_currQueue);

	_uta->clear();

	// Add rectangles of objects which don't exist in this frame any more
	for (RenderObjectQueue::iterator it = _prevQueue->begin(); it != _prevQueue->end(); ++it) {
		if (!_currQueue->exists(*it))
			_uta->addRect((*it)._bbox);
	}

	// Add rectangles of objects which are different from the previous frame
	for (RenderObjectQueue::iterator it = _currQueue->begin(); it != _currQueue->end(); ++it) {
		if (!_prevQueue->exists(*it))
			_uta->addRect((*it)._bbox);
	}

	RectangleList *updateRects = _uta->getRectangles();
	Common::Array<int> updateRectsMinZ;

	updateRectsMinZ.reserve(updateRects->size());

	// Calculate the minimum drawing Z value of each update rectangle
	// Solid bitmaps with a Z order less than the value calculated here would be overdrawn again and
	// so don't need to be drawn in the first place which speeds things up a bit.
	for (RectangleList::iterator rectIt = updateRects->begin(); rectIt != updateRects->end(); ++rectIt) {
		int minZ = 0;
		for (RenderObjectQueue::iterator it = _currQueue->reverse_begin(); it != _currQueue->end(); --it) {
			if ((*it)._renderObject->isVisible() && (*it)._renderObject->isSolid() &&
				(*it)._renderObject->getBbox().contains(*rectIt)) {
				minZ = (*it)._renderObject->getAbsoluteZ();
				break;
			}
		}
		updateRectsMinZ.push_back(minZ);
	}

	if (_rootPtr->render(updateRects, updateRectsMinZ)) {
		// Copy updated rectangles to the video screen
		Graphics::Surface *backSurface = Kernel::getInstance()->getGfx()->getSurface();
		for (RectangleList::iterator rectIt = updateRects->begin(); rectIt != updateRects->end(); ++rectIt) {
			const int x = (*rectIt).left;
			const int y = (*rectIt).top;
			const int width = (*rectIt).width();
			const int height = (*rectIt).height();
			g_system->copyRectToScreen(backSurface->getBasePtr(x, y), backSurface->pitch, x, y, width, height);
		}
	}

	delete updateRects;

	SWAP(_currQueue, _prevQueue);

	return true;
}
void LowLevelGraphicsPostScriptRenderer::fillRectList (const RectangleList<float>& list)
{
    fillPath (list.toPath(), AffineTransform::identity);
}
bool OpenGLComponent::performRender()
{
    const ScopedLock sl (contextLock);

   #if JUCE_LINUX
    updateContext();
   #endif

    if (context != nullptr)
    {
        if (! makeCurrentRenderingTarget())
            return false;

        if (needToUpdateViewport)
        {
            needToUpdateViewport = false;
            glViewport (0, 0, getWidth(), getHeight());
        }

        renderOpenGL();

        if (needToRepaint && (flags & allowSubComponents) != 0)
        {
            needToRepaint = false;

            contextLock.exit(); // (MM must be locked before the context lock)
            MessageManagerLock mmLock (renderThread);
            contextLock.enter();

            if (! mmLock.lockWasGained())
                return false;

            // you mustn't set your own cached image object for an OpenGLComponent!
            jassert (dynamic_cast<OpenGLCachedComponentImage*> (getCachedComponentImage()) == cachedImage);

            const Rectangle<int> bounds (getLocalBounds());
            OpenGLFrameBuffer& frameBuffer = cachedImage->getFrameBuffer (bounds.getWidth(), bounds.getHeight());

            {
                RectangleList invalid (bounds);
                invalid.subtract (cachedImage->validArea);
                cachedImage->validArea = bounds;

                if (! invalid.isEmpty())
                {
                    jassert (getCurrentContext() != nullptr);

                    {
                        OpenGLGraphicsContext g (*getCurrentContext(), frameBuffer);
                        g.clipToRectangleList (invalid);

                        g.setFill (Colours::transparentBlack);
                        g.fillRect (bounds, true);
                        g.setFill (Colours::black);

                        paintSelf (g);
                    }

                    makeCurrentRenderingTarget();
                }
            }

            glEnable (GL_TEXTURE_2D);
            context->extensions.glActiveTexture (GL_TEXTURE0);
            glBindTexture (GL_TEXTURE_2D, frameBuffer.getTextureID());

            context->copyTexture (bounds, Rectangle<int> (bounds.getWidth(),
                                                          bounds.getHeight()));
            glBindTexture (GL_TEXTURE_2D, 0);
        }

        swapBuffers();
    }

    return true;
}
void Graphics::fillRectList (const RectangleList<int>& rects) const
{
    for (const Rectangle<int>* r = rects.begin(), * const e = rects.end(); r != e; ++r)
        context.fillRect (*r, false);
}