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(); }
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); }
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; }
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)); }
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; }
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()); } }
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(); } }
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); }
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); }