GuiWidget *findNextWidgetToFocus(WalkDirection dir) { PopupWidget *parentPopup = self().findParentPopup(); Rectanglei const viewRect = self().root().viewRule().recti(); bool escaped = false; auto *widget = self().walkInOrder(dir, [this, &viewRect, parentPopup, &escaped] (Widget &widget) { if (parentPopup && !widget.hasAncestor(*parentPopup)) { // Cannot get out of the popup. escaped = true; return LoopAbort; } if (widget.canBeFocused() && widget.is<GuiWidget>()) { // The widget's center must be in view. if (viewRect.contains(widget.as<GuiWidget>().rule().recti().middle())) { // This is good. return LoopAbort; } } return LoopContinue; }); if (widget && !escaped) { return widget->asPtr<GuiWidget>(); } return nullptr; }
/** * Test if a clipped widget is contained within its ancestors' clip rectangles. */ bool isClipCulled() const { bool wasClipped = false; Rectanglei visibleArea = self().root().viewRule().recti(); for (Widget const *w = self().parentWidget(); w; w = w->parent()) { if (!w->is<GuiWidget>()) continue; // Does this ancestor use child clipping? if (w->behavior().testFlag(ChildVisibilityClipping)) { wasClipped = true; visibleArea &= w->as<GuiWidget>().rule().recti(); } } if (!wasClipped) return false; if (self().isClipped()) { int const CULL_SAFETY_WIDTH = 50; // avoid pop-in when scrolling // Clipped widgets are guaranteed to be within their rectangle. return !visibleArea.overlaps(self().rule().recti().expanded( GuiWidget::toDevicePixels(CULL_SAFETY_WIDTH))); } // Otherwise widgets may draw anywhere in the view. return visibleArea.isNull(); }
static void drawRegion(memvolume_t &volume, Rectanglei const &rect, size_t start, size_t size, float const color[4]) { DENG2_ASSERT(start + size <= volume.size); int const bytesPerRow = (volume.size - sizeof(memzone_t)) / rect.height(); float const toPixelScale = (float)rect.width() / (float)bytesPerRow; size_t const edge = rect.topLeft.x + rect.width(); int x = (start % bytesPerRow) * toPixelScale + rect.topLeft.x; int y = start / bytesPerRow + rect.topLeft.y; int pixels = de::max<dint>(1, std::ceil(size * toPixelScale)); while(pixels > 0) { int const availPixels = edge - x; int const usedPixels = de::min(availPixels, pixels); glColor4fv(color); glVertex2i(x, y); glVertex2i(x + usedPixels, y); pixels -= usedPixels; // Move to the next row. y++; x = rect.topLeft.x; } }
bool WidgetList::Update(const Point2i& mousePosition, const Point2i& lastMousePosition) { Rectanglei clip; Rectanglei wlr = GetClip(clip); if (!wlr.GetSizeX() || !wlr.GetSizeY()) return false; // Redraw the background bool updated = false; if (need_redrawing) RedrawBackground(wlr); for (std::list<Widget*>::const_iterator w=widget_list.begin(); w != widget_list.end(); w++) { Rectanglei r((*w)->GetPosition(), (*w)->GetSize()); r.Clip(wlr); if (r.GetSizeX() && r.GetSizeY()) { SwapWindowClip(r); updated |= (*w)->Update(mousePosition, lastMousePosition); SwapWindowClip(r); } } if (updated) RedrawForeground(); // Restore initial clip rectangle UnsetClip(clip); need_redrawing = false; return updated; }
void LineEditWidget::draw() { Rectanglei pos = rule().recti(); // Temporary buffer for drawing. TextCanvas buf(pos.size()); TextCanvas::Char::Attribs attr = (hasFocus()? TextCanvas::Char::Reverse : TextCanvas::Char::DefaultAttributes); buf.clear(TextCanvas::Char(' ', attr)); buf.drawText(Vector2i(0, 0), prompt(), attr | TextCanvas::Char::Bold); // Underline the suggestion for completion. if(isSuggestingCompletion()) { buf.setRichFormatRange(TextCanvas::Char::Underline, completionRange()); } // Echo mode determines what we actually draw. String txt = text(); if(echoMode() == PasswordEchoMode) { txt = String(txt.size(), '*'); } buf.drawWrappedText(Vector2i(prompt().size(), 0), txt, lineWraps(), attr); targetCanvas().draw(buf, pos.topLeft); }
QImage QtNativeFont::nativeFontRasterize(String const &text, Vector4ub const &foreground, Vector4ub const &background) const { #ifdef LIBGUI_ACCURATE_TEXT_BOUNDS Rectanglei const bounds = measure(text); #else Rectanglei const bounds(Vector2i(0, -d->metrics->ascent()), Vector2i(d->metrics->width(text), d->metrics->descent())); #endif QColor const fgColor(foreground.x, foreground.y, foreground.z, foreground.w); QColor const bgColor(background.x, background.y, background.z, background.w); QImage img(QSize(bounds.width() + 1, bounds.height() + 1), QImage::Format_ARGB32); img.fill(bgColor.rgba()); QPainter painter(&img); painter.setCompositionMode(QPainter::CompositionMode_Source); painter.setFont(d->font); painter.setPen(fgColor); painter.setBrush(bgColor); painter.drawText(-bounds.left(), -bounds.top(), text); return img; }
void LabelWidget::draw() { Rectanglei pos = rule().recti(); TextCanvas buf(pos.size()); buf.clear(d->background); // Use the wrapped lines to determine width and height. DENG2_ASSERT(!d->wraps.isEmpty()); Vector2i labelSize(d->wraps.width(), d->wraps.height()); // Determine position of the label based on alignment. Vector2i labelPos; if(d->align.testFlag(AlignRight)) { labelPos.x = buf.width() - labelSize.x; } else if(!d->align.testFlag(AlignLeft)) { labelPos.x = buf.width()/2 - labelSize.x/2; } if(d->align.testFlag(AlignBottom)) { labelPos.y = buf.height() - labelSize.y; } else if(!d->align.testFlag(AlignTop)) { labelPos.y = buf.height()/2 - labelSize.y/2; } buf.drawWrappedText(labelPos, d->label, d->wraps, d->attribs, d->align); targetCanvas().draw(buf, pos.topLeft); }
void WidgetList::Draw(const Point2i &mousePosition) { Rectanglei clip; Rectanglei wlr = GetClip(clip); if (!wlr.GetSizeX() || !wlr.GetSizeY()) return; for (std::list<Widget*>::const_iterator w=widget_list.begin(); w != widget_list.end(); w++) { Rectanglei r((*w)->GetPosition(), (*w)->GetSize()); r.Clip(wlr); if (r.GetSizeX() && r.GetSizeY()) { Rectanglei wr = r; SwapWindowClip(r); (*w)->RedrawBackground(wr); (*w)->Draw(mousePosition); (*w)->RedrawForeground(); SwapWindowClip(r); } } // Restore initial clip rectangle UnsetClip(clip); }
void BoundTexture2d::update_data(const Rectanglei& update_region, Texture::DataPixelFormat data_format, Texture::PixelType pixel_type, const void* data) { glTexSubImage2D(GL_TEXTURE_2D, 0, update_region.left(), update_region.bottom(), update_region.width(), update_region.height(), static_cast<GLenum>(data_format), static_cast<GLenum>(pixel_type), data); CHECK_GL_ERROR(glTexSubImage2D); }
static void drawChar(uchar ch, float x, float y, AbstractFont *font, int alignFlags, short /*textFlags*/) { if(alignFlags & ALIGN_RIGHT) { x -= font->glyphPosCoords(ch).width(); } else if(!(alignFlags & ALIGN_LEFT)) { x -= font->glyphPosCoords(ch).width() / 2; } int const ascent = font->ascent(); int const lineHeight = ascent? ascent : font->glyphPosCoords(ch).height(); if(alignFlags & ALIGN_BOTTOM) { y -= topToAscent(font) + lineHeight; } else if(!(alignFlags & ALIGN_TOP)) { y -= (topToAscent(font) + lineHeight) / 2; } LIBGUI_GL.glMatrixMode(GL_MODELVIEW); LIBGUI_GL.glTranslatef(x, y, 0); Rectanglei geometry = font->glyphPosCoords(ch); if(BitmapFont *bmapFont = font->maybeAs<BitmapFont>()) { /// @todo Filtering should be determined at a higher level. /// @todo We should not need to re-bind this texture here. GL_BindTextureUnmanaged(bmapFont->textureGLName(), gl::ClampToEdge, gl::ClampToEdge, filterUI? gl::Linear : gl::Nearest); geometry = geometry.expanded(bmapFont->textureMargin().toVector2i()); } else if(CompositeBitmapFont *compFont = font->maybeAs<CompositeBitmapFont>()) { GL_BindTexture(compFont->glyphTexture(ch)); geometry = geometry.expanded(compFont->glyphTextureBorder(ch)); } Vector2i coords[4] = { font->glyphTexCoords(ch).topLeft, font->glyphTexCoords(ch).topRight(), font->glyphTexCoords(ch).bottomRight, font->glyphTexCoords(ch).bottomLeft() }; GL_DrawRectWithCoords(geometry, coords); if(font->is<CompositeBitmapFont>()) { GL_SetNoTexture(); } LIBGUI_GL.glMatrixMode(GL_MODELVIEW); LIBGUI_GL.glTranslatef(-x, -y, 0); }
void TextBox::Draw(const Point2i & mousePosition) { Rectanglei clip; Rectanglei wlr = GetClip(clip); if (!wlr.GetSizeX() || !wlr.GetSizeY()) return; Label::Draw(mousePosition); DrawCursor(position, cursor_pos); // Restore initial clip rectangle UnsetClip(clip); }
Rectanglei QtNativeFont::nativeFontMeasure(String const &text) const { Rectanglei rect = Rectanglei::fromQRect(d->metrics->boundingRect(text)); if(rect.height() == 0) { // It seems measuring the bounds of a Tab character produces // strange results (position 100000?). rect = Rectanglei(0, 0, rect.width(), 0); } return rect; }
int SpriteAni::addFrame(int image_id, const Rectanglei &rect) { AniFrame *ani_frame = new AniFrame; ani_frame->id = (uint16)frame_seq.size(); ani_frame->image = image_id; ani_frame->rect.x = rect.getLeft(); ani_frame->rect.y = rect.getTop(); ani_frame->rect.w = rect.getWidth(); ani_frame->rect.h = rect.getHeight(); frame_seq.push_back(ani_frame); return ani_frame->id; }
void Menu::RedrawBackground(const Rectanglei & rect) const { if (!background) { return; } background->Blit(GetMainWindow(), rect, rect.GetPosition()); }
/* bool VirtualKeyboardParser::parsePolygon(Polygon &poly, const String& coords) { StringTokenizer tok(coords, ", "); for (String st = tok.nextToken(); !st.empty(); st = tok.nextToken()) { int x, y; if (sscanf(st.c_str(), "%d", &x) != 1) return parserError("Invalid coords for polygon area"); st = tok.nextToken(); if (sscanf(st.c_str(), "%d", &y) != 1) return parserError("Invalid coords for polygon area"); poly.addPoint(x, y); } if (poly.getPointCount() < 3) return parserError("Invalid coords for polygon area"); return true; } */ bool VirtualKeyboardParser::parseRectAsPolygon(Polygon &poly, const string& coords) { Rectanglei rect; if (!parseRect(rect, coords)) return false; poly.addPoint(rect.GetLeft(), rect.GetTop()); poly.addPoint(rect.GetRight(), rect.GetTop()); poly.addPoint(rect.GetRight(), rect.GetBottom()); poly.addPoint(rect.GetLeft(), rect.GetBottom()); return true; }
void RectangleTest::access() { Rectanglei rect({34, 23}, {47, 30}); constexpr Rectanglei crect({34, 23}, {47, 30}); CORRADE_COMPARE(rect.bottomLeft(), Vector2i(34, 23)); CORRADE_COMPARE(rect.topRight(), Vector2i(47, 30)); CORRADE_COMPARE(rect.bottom(), 23); CORRADE_COMPARE(rect.top(), 30); CORRADE_COMPARE(rect.left(), 34); CORRADE_COMPARE(rect.right(), 47); CORRADE_COMPARE(rect.bottomLeft(), Vector2i(34, 23)); CORRADE_COMPARE(rect.topRight(), Vector2i(47, 30)); constexpr Int bottom = crect.bottom(); constexpr Int top = crect.top(); constexpr Int left = crect.left(); constexpr Int right = crect.right(); CORRADE_COMPARE(bottom, 23); CORRADE_COMPARE(top, 30); CORRADE_COMPARE(left, 34); CORRADE_COMPARE(right, 47); constexpr Vector2i bottomLeft = crect.bottomLeft(); constexpr Vector2i topRight = crect.topRight(); CORRADE_COMPARE(bottomLeft, Vector2i(34, 23)); CORRADE_COMPARE(topRight, Vector2i(47, 30)); CORRADE_COMPARE(rect.topLeft(), Vector2i(34, 30)); CORRADE_COMPARE(rect.bottomRight(), Vector2i(47, 23)); }
void draw() { Rectanglei pos; if(self.hasChangedPlace(pos) || !bgBuf->isReady()) { // Update the background quad. VertexBuf::Builder bgVerts; self.glMakeGeometry(bgVerts); bgBuf->setVertices(gl::TriangleStrip, bgVerts, gl::Static); } // Draw the background. background.draw(); Rectanglei vp = self.viewport(); if(vp.height() > 0) { GLState &st = GLState::push(); // Leave room for the indicator in the scissor. st.setScissor(vp.adjusted(Vector2i(), Vector2i(self.rightMargin(), 0))); // First draw the shadow of the text. uMvpMatrix = projMatrix * Matrix4f::translate( Vector2f(vp.topLeft + Vector2i(0, contentOffsetForDrawing))); uShadowColor = Vector4f(0, 0, 0, 1); contents.draw(); // Draw the text itself. uMvpMatrix = projMatrix * Matrix4f::translate( Vector2f(vp.topLeft + Vector2i(0, contentOffsetForDrawing - 1))); uShadowColor = Vector4f(1, 1, 1, 1); contents.draw(); GLState::pop(); } // We don't need to keep all entries ready for drawing immediately. releaseExcessComposedEntries(); }
inline bool PhysicalObj::Intersect(const Rectanglei & rect) const { int dim = m_width - m_test_right - m_test_left; dim = dim ? dim : 1; int obj_test1 = GetX() + m_test_left; int obj_test2 = obj_test1 + dim - 1; int test1 = rect.GetPositionX(); int test2 = test1 + rect.GetSizeX() - 1; if (obj_test2 >= test1 && obj_test1 <= test2) { dim = m_height - m_test_bottom - m_test_top; dim = dim ? dim : 1; obj_test1 = GetY() + m_test_top; obj_test2 = obj_test1 + dim - 1; test1 = rect.GetPositionY(); test2 = test1 + rect.GetSizeY() - 1; if (obj_test2 >= test1 && obj_test1 <= test2) return true; } return false; }
duint CanvasWindow::grabAsTexture(Rectanglei const &area, GrabMode mode) const { QSize size; if(mode == GrabHalfSized) { size = QSize(area.width()/2, area.height()/2); } return d->canvas->grabAsTexture( QRect(area.left(), area.top(), area.width(), area.height()), size); }
void glSubImage(int level, Rectanglei const &rect, Image const &image, CubeFace face = PositiveX) { auto const &glFormat = image.glFormat(); LIBGUI_GL.glPixelStorei(GL_UNPACK_ALIGNMENT, GLint(glFormat.rowAlignment)); LIBGUI_GL.glPixelStorei(GL_UNPACK_ROW_LENGTH, GLint(image.width())); int const bytesPerPixel = image.depth() / 8; LIBGUI_GL.glTexSubImage2D(isCube()? glFace(face) : texTarget, level, rect.left(), rect.top(), rect.width(), rect.height(), glFormat.format, glFormat.type, static_cast<dbyte const *>(image.bits()) + bytesPerPixel * rect.left() + image.stride() * rect.top()); LIBGUI_GL.glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); LIBGUI_ASSERT_GL_OK(); }
/** * Submits the image to the backing store, or commits it if no backing * store is available. * * @param image Image. * @param rect Rectangle for the image determined by an IAllocator. */ void submitImage(Image const &image, Rectanglei const &rect) { Rectanglei const noBorders = rect.shrunk(border); Rectanglei const withMargin = rect.expanded(margin); if (hasBacking()) { // The margin is cleared to transparent black. backing.fill(withMargin, Image::Color(0, 0, 0, 0)); if (border > 0) { if (flags.testFlag(WrapBordersInBackingStore)) { // Wrap using the source image (left, right, top, bottom edges). backing.drawPartial(image, Rectanglei(0, 0, border, image.height()), rect.topRight() + Vector2i(-border, border)); backing.drawPartial(image, Rectanglei(image.width() - border, 0, border, image.height()), rect.topLeft + Vector2i(0, border)); backing.drawPartial(image, Rectanglei(0, 0, image.width(), border), rect.bottomLeft() + Vector2i(border, -border)); backing.drawPartial(image, Rectanglei(0, image.height() - border, image.width(), border), rect.topLeft + Vector2i(border, 0)); } } backing.draw(image, noBorders.topLeft); //backing.toQImage().save(QString("backing-%1.png").arg(uint64_t(this))); markAsChanged(rect); } else { // No backing, must commit immediately. if (border > 0) { // Expand with borders (repeat edges). QImage const srcImg = image.toQImage(); int const sw = srcImg.width(); int const sh = srcImg.height(); QImage bordered(QSize(rect.width(), rect.height()), srcImg.format()); int const w = bordered.width(); int const h = bordered.height(); QPainter painter(&bordered); painter.setCompositionMode(QPainter::CompositionMode_Source); painter.fillRect(bordered.rect(), QColor(0, 0, 0, 0)); /// @todo This really only works for a border of 1 pixels. Should /// repeat the same outmost edge pixels for every border. -jk painter.drawImage(border, border, srcImg); painter.drawImage(border, 0, srcImg, 0, 0, sw, 1); // top painter.drawImage(border, h - 1, srcImg, 0, sh - 1, sw, 1); // bottom painter.drawImage(0, border, srcImg, 0, 0, 1, sh); // left painter.drawImage(w - 1, border, srcImg, sw - 1, 0, 1, sh); // right // Corners. painter.drawImage(0, 0, srcImg, 0, 0, 1, 1); painter.drawImage(w - 1, 0, srcImg, sw - 1, 0, 1, 1); painter.drawImage(0, h - 1, srcImg, 0, sh - 1, 1, 1); painter.drawImage(w - 1, h - 1, srcImg, sw - 1, sh - 1, 1, 1); self().commit(bordered, rect.topLeft); } else { self().commit(image, noBorders.topLeft); } } }
namespace Magnum { namespace Math { namespace Geometry { namespace Test { class RectangleTest: public Corrade::TestSuite::Tester { public: RectangleTest(); void construct(); void constructDefault(); void constructFromSize(); void constructConversion(); void constructCopy(); void access(); void compare(); void size(); void debug(); }; typedef Geometry::Rectangle<Float> Rectangle; typedef Geometry::Rectangle<Int> Rectanglei; typedef Vector2<Int> Vector2i; RectangleTest::RectangleTest() { addTests({&RectangleTest::construct, &RectangleTest::constructDefault, &RectangleTest::constructFromSize, &RectangleTest::constructConversion, &RectangleTest::constructCopy, &RectangleTest::access, &RectangleTest::compare, &RectangleTest::size, &RectangleTest::debug}); } void RectangleTest::construct() { constexpr Rectanglei a({3, 5}, {23, 78}); CORRADE_COMPARE(a, Rectanglei({3, 5}, {23, 78})); } void RectangleTest::constructDefault() { constexpr Rectanglei a; CORRADE_COMPARE(a, Rectanglei({0, 0}, {0, 0})); } void RectangleTest::constructFromSize() { CORRADE_COMPARE(Rectanglei::fromSize({3, 5}, {23, 78}), Rectanglei({3, 5}, {26, 83})); } void RectangleTest::constructConversion() { constexpr Rectangle a({1.3f, 2.7f}, {-15.0f, 7.0f}); #ifndef CORRADE_GCC46_COMPATIBILITY constexpr /* Not constexpr under GCC < 4.7 */ #endif Rectanglei b(a); CORRADE_COMPARE(b, Rectanglei({1, 2}, {-15, 7})); /* Implicit conversion is not allowed */ CORRADE_VERIFY(!(std::is_convertible<Rectangle, Rectanglei>::value)); } void RectangleTest::constructCopy() { constexpr Rectanglei a({3, 5}, {23, 78}); constexpr Rectanglei b(a); CORRADE_COMPARE(b, Rectanglei({3, 5}, {23, 78})); } void RectangleTest::access() { Rectanglei rect({34, 23}, {47, 30}); constexpr Rectanglei crect({34, 23}, {47, 30}); CORRADE_COMPARE(rect.bottomLeft(), Vector2i(34, 23)); CORRADE_COMPARE(rect.topRight(), Vector2i(47, 30)); CORRADE_COMPARE(rect.bottom(), 23); CORRADE_COMPARE(rect.top(), 30); CORRADE_COMPARE(rect.left(), 34); CORRADE_COMPARE(rect.right(), 47); CORRADE_COMPARE(rect.bottomLeft(), Vector2i(34, 23)); CORRADE_COMPARE(rect.topRight(), Vector2i(47, 30)); constexpr Int bottom = crect.bottom(); constexpr Int top = crect.top(); constexpr Int left = crect.left(); constexpr Int right = crect.right(); CORRADE_COMPARE(bottom, 23); CORRADE_COMPARE(top, 30); CORRADE_COMPARE(left, 34); CORRADE_COMPARE(right, 47); constexpr Vector2i bottomLeft = crect.bottomLeft(); constexpr Vector2i topRight = crect.topRight(); CORRADE_COMPARE(bottomLeft, Vector2i(34, 23)); CORRADE_COMPARE(topRight, Vector2i(47, 30)); CORRADE_COMPARE(rect.topLeft(), Vector2i(34, 30)); CORRADE_COMPARE(rect.bottomRight(), Vector2i(47, 23)); } void RectangleTest::compare() { CORRADE_VERIFY(Rectanglei({34, 23}, {47, 30}) == Rectanglei({34, 23}, {47, 30})); CORRADE_VERIFY(Rectanglei({34, 23}, {47, 30}) != Rectanglei({34, 23}, {48, 30})); CORRADE_VERIFY(Rectanglei({34, 23}, {47, 30}) != Rectanglei({35, 23}, {47, 30})); } void RectangleTest::size() { Rectanglei rect({34, 23}, {47, 30}); CORRADE_COMPARE(rect.size(), Vector2i(13, 7)); CORRADE_COMPARE(rect.width(), 13); CORRADE_COMPARE(rect.height(), 7); } void RectangleTest::debug() { std::ostringstream o; Debug(&o) << Rectanglei({34, 23}, {47, 30}); CORRADE_COMPARE(o.str(), "Rectangle({34, 23}, {47, 30})\n"); } }}}}