void RenderImage::updateInnerContentRect() { // Propagate container size to the image resource. LayoutRect containerRect = replacedContentRect(); IntSize containerSize(containerRect.width(), containerRect.height()); if (!containerSize.isEmpty()) m_imageResource->setContainerSizeForRenderer(containerSize); }
void BoxLayout::performLayout(NVGcontext *ctx, Widget *widget) const { Vector2i fs_w = widget->fixedSize(); Vector2i containerSize( fs_w[0] ? fs_w[0] : widget->width(), fs_w[1] ? fs_w[1] : widget->height() ); int axis1 = (int) mOrientation, axis2 = ((int) mOrientation + 1)%2; int position = mMargin; if (dynamic_cast<Window *>(widget)) position += widget->theme()->mWindowHeaderHeight - mMargin/2; bool first = true; for (auto w : widget->children()) { if (!w->visible()) continue; if (first) first = false; else position += mSpacing; Vector2i ps = w->preferredSize(ctx), fs = w->fixedSize(); Vector2i targetSize( fs[0] ? fs[0] : ps[0], fs[1] ? fs[1] : ps[1] ); Vector2i pos = Vector2i::Zero(); pos[axis1] = position; switch (mAlignment) { case Alignment::Minimum: pos[axis2] = mMargin; break; case Alignment::Middle: pos[axis2] = (containerSize[axis2] - targetSize[axis2]) / 2; break; case Alignment::Maximum: pos[axis2] = containerSize[axis2] - targetSize[axis2] - mMargin; break; case Alignment::Fill: pos[axis2] = mMargin; targetSize[axis2] = fs[axis2] ? fs[axis2] : containerSize[axis2]; break; } w->setPosition(pos); w->setSize(targetSize); w->performLayout(ctx); position += targetSize[axis1]; } }
bool SVGImage::dataChanged(bool allDataReceived) { TRACE_EVENT0("webkit", "SVGImage::dataChanged"); // Don't do anything if is an empty image. if (!data()->size()) return true; if (allDataReceived) { static FrameLoaderClient* dummyFrameLoaderClient = new EmptyFrameLoaderClient; Page::PageClients pageClients; fillWithEmptyClients(pageClients); m_chromeClient = adoptPtr(new SVGImageChromeClient(this)); pageClients.chromeClient = m_chromeClient.get(); // FIXME: If this SVG ends up loading itself, we might leak the world. // The Cache code does not know about ImageResources holding Frames and // won't know to break the cycle. // This will become an issue when SVGImage will be able to load other // SVGImage objects, but we're safe now, because SVGImage can only be // loaded by a top-level document. m_page = adoptPtr(new Page(pageClients)); m_page->settings().setMediaEnabled(false); m_page->settings().setScriptEnabled(false); m_page->settings().setPluginsEnabled(false); m_page->settings().setAcceleratedCompositingEnabled(false); RefPtr<Frame> frame = Frame::create(FrameInit::create(0, m_page.get(), dummyFrameLoaderClient)); frame->setView(FrameView::create(frame.get())); frame->init(); FrameLoader& loader = frame->loader(); loader.forceSandboxFlags(SandboxAll); frame->view()->setScrollbarsSuppressed(true); frame->view()->setCanHaveScrollbars(false); // SVG Images will always synthesize a viewBox, if it's not available, and thus never see scrollbars. frame->view()->setTransparent(true); // SVG Images are transparent. ASSERT(loader.activeDocumentLoader()); // DocumentLoader should have been created by frame->init(). DocumentWriter* writer = loader.activeDocumentLoader()->beginWriting("image/svg+xml", "UTF-8"); writer->addData(data()->data(), data()->size()); loader.activeDocumentLoader()->endWriting(writer); // Set the intrinsic size before a container size is available. m_intrinsicSize = containerSize(); } return m_page; }
void SVGImage::draw(SkCanvas* canvas, const SkPaint& paint, const FloatRect& dstRect, const FloatRect& srcRect, RespectImageOrientationEnum, ImageClampingMode) { if (!m_page) return; FrameView* view = frameView(); view->resize(containerSize()); // Always call processUrlFragment, even if the url is empty, because // there may have been a previous url/fragment that needs to be reset. view->processUrlFragment(m_url); SkPictureBuilder imagePicture(dstRect); { ClipRecorder clipRecorder(imagePicture.context(), *this, DisplayItem::ClipNodeImage, LayoutRect(enclosingIntRect(dstRect))); // We can only draw the entire frame, clipped to the rect we want. So compute where the top left // of the image would be if we were drawing without clipping, and translate accordingly. FloatSize scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height()); FloatSize topLeftOffset(srcRect.location().x() * scale.width(), srcRect.location().y() * scale.height()); FloatPoint destOffset = dstRect.location() - topLeftOffset; AffineTransform transform = AffineTransform::translation(destOffset.x(), destOffset.y()); transform.scale(scale.width(), scale.height()); TransformRecorder transformRecorder(imagePicture.context(), *this, transform); view->updateAllLifecyclePhases(); view->paint(&imagePicture.context(), enclosingIntRect(srcRect)); ASSERT(!view->needsLayout()); } { SkAutoCanvasRestore ar(canvas, false); if (drawNeedsLayer(paint)) { SkRect layerRect = dstRect; canvas->saveLayer(&layerRect, &paint); } RefPtr<const SkPicture> recording = imagePicture.endRecording(); canvas->drawPicture(recording.get()); } if (imageObserver()) imageObserver()->didDraw(this); // Start any (SMIL) animations if needed. This will restart or continue // animations if preceded by calls to resetAnimation or stopAnimation // respectively. startAnimation(); }
void SVGImage::draw(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp, BlendMode blendMode, ImageOrientationDescription) { if (!m_page) return; FrameView* view = frameView(); ASSERT(view); GraphicsContextStateSaver stateSaver(context); context.setCompositeOperation(compositeOp, blendMode); context.clip(enclosingIntRect(dstRect)); float alpha = context.alpha(); bool compositingRequiresTransparencyLayer = compositeOp != CompositeSourceOver || blendMode != BlendModeNormal || alpha < 1; if (compositingRequiresTransparencyLayer) { context.beginTransparencyLayer(alpha); context.setCompositeOperation(CompositeSourceOver, BlendModeNormal); } FloatSize scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height()); // We can only draw the entire frame, clipped to the rect we want. So compute where the top left // of the image would be if we were drawing without clipping, and translate accordingly. FloatSize topLeftOffset(srcRect.location().x() * scale.width(), srcRect.location().y() * scale.height()); FloatPoint destOffset = dstRect.location() - topLeftOffset; context.translate(destOffset.x(), destOffset.y()); context.scale(scale); view->resize(containerSize()); if (!m_url.isEmpty()) view->scrollToFragment(m_url); if (view->needsLayout()) view->layout(); view->paint(context, intersection(context.clipBounds(), enclosingIntRect(srcRect))); if (compositingRequiresTransparencyLayer) context.endTransparencyLayer(); stateSaver.restore(); if (imageObserver()) imageObserver()->didDraw(this); }
bool SVGImage::dataChanged(bool allDataReceived) { // Don't do anything if is an empty image. if (!data()->size()) return true; if (allDataReceived) { PageConfiguration pageConfiguration(makeUniqueRef<EmptyEditorClient>(), SocketProvider::create()); fillWithEmptyClients(pageConfiguration); m_chromeClient = std::make_unique<SVGImageChromeClient>(this); pageConfiguration.chromeClient = m_chromeClient.get(); // FIXME: If this SVG ends up loading itself, we might leak the world. // The Cache code does not know about CachedImages holding Frames and // won't know to break the cycle. // This will become an issue when SVGImage will be able to load other // SVGImage objects, but we're safe now, because SVGImage can only be // loaded by a top-level document. m_page = std::make_unique<Page>(WTFMove(pageConfiguration)); m_page->settings().setMediaEnabled(false); m_page->settings().setScriptEnabled(false); m_page->settings().setPluginsEnabled(false); m_page->settings().setAcceleratedCompositingEnabled(false); Frame& frame = m_page->mainFrame(); frame.setView(FrameView::create(frame)); frame.init(); FrameLoader& loader = frame.loader(); loader.forceSandboxFlags(SandboxAll); frame.view()->setCanHaveScrollbars(false); // SVG Images will always synthesize a viewBox, if it's not available, and thus never see scrollbars. frame.view()->setTransparent(true); // SVG Images are transparent. ASSERT(loader.activeDocumentLoader()); // DocumentLoader should have been created by frame->init(). loader.activeDocumentLoader()->writer().setMIMEType("image/svg+xml"); loader.activeDocumentLoader()->writer().begin(URL()); // create the empty document loader.activeDocumentLoader()->writer().addData(data()->data(), data()->size()); loader.activeDocumentLoader()->writer().end(); // Set the intrinsic size before a container size is available. m_intrinsicSize = containerSize(); reportApproximateMemoryCost(); } return m_page != nullptr; }
bool SVGImage::dataChanged(bool allDataReceived) { TRACE_EVENT0("webkit", "SVGImage::dataChanged"); // Don't do anything if is an empty image. if (!data()->size()) return true; if (allDataReceived) { static FrameLoaderClient* dummyFrameLoaderClient = new EmptyFrameLoaderClient; Page::PageClients pageClients; fillWithEmptyClients(pageClients); m_chromeClient = adoptPtr(new SVGImageChromeClient(this)); pageClients.chromeClient = m_chromeClient.get(); // FIXME: If this SVG ends up loading itself, we might leak the world. // The Cache code does not know about ImageResources holding Frames and // won't know to break the cycle. // This will become an issue when SVGImage will be able to load other // SVGImage objects, but we're safe now, because SVGImage can only be // loaded by a top-level document. OwnPtr<Page> page = adoptPtr(new Page(pageClients)); page->settings().setScriptEnabled(false); page->settings().setPluginsEnabled(false); page->settings().setAcceleratedCompositingEnabled(false); RefPtr<LocalFrame> frame = LocalFrame::create(dummyFrameLoaderClient, &page->frameHost(), 0); frame->setView(FrameView::create(frame.get())); frame->init(); FrameLoader& loader = frame->loader(); loader.forceSandboxFlags(SandboxAll); frame->view()->setScrollbarsSuppressed(true); frame->view()->setCanHaveScrollbars(false); // SVG Images will always synthesize a viewBox, if it's not available, and thus never see scrollbars. frame->view()->setTransparent(true); // SVG Images are transparent. m_page = page.release(); loader.load(FrameLoadRequest(0, blankURL(), SubstituteData(data(), "image/svg+xml", "UTF-8", KURL(), ForceSynchronousLoad))); // Set the intrinsic size before a container size is available. m_intrinsicSize = containerSize(); } return m_page; }
bool SVGImage::dataChanged(bool allDataReceived) { // Don't do anything if is an empty image. if (!data()->size()) return true; if (allDataReceived) { Page::PageClients pageClients; fillWithEmptyClients(pageClients); m_chromeClient = adoptPtr(new SVGImageChromeClient(this)); pageClients.chromeClient = m_chromeClient.get(); // FIXME: If this SVG ends up loading itself, we might leak the world. // The Cache code does not know about CachedImages holding Frames and // won't know to break the cycle. // This will become an issue when SVGImage will be able to load other // SVGImage objects, but we're safe now, because SVGImage can only be // loaded by a top-level document. m_page = adoptPtr(new Page(pageClients)); m_page->settings().setMediaEnabled(false); m_page->settings().setScriptEnabled(false); m_page->settings().setPluginsEnabled(false); Frame& frame = m_page->mainFrame(); frame.setView(FrameView::create(&frame)); frame.init(); FrameLoader& loader = frame.loader(); loader.forceSandboxFlags(SandboxAll); frame.view()->setCanHaveScrollbars(false); // SVG Images will always synthesize a viewBox, if it's not available, and thus never see scrollbars. frame.view()->setTransparent(true); // SVG Images are transparent. ASSERT(loader.activeDocumentLoader()); // DocumentLoader should have been created by frame->init(). loader.activeDocumentLoader()->writer()->setMIMEType("image/svg+xml"); loader.activeDocumentLoader()->writer()->begin(KURL()); // create the empty document loader.activeDocumentLoader()->writer()->addData(data()->data(), data()->size()); loader.activeDocumentLoader()->writer()->end(); // Set the intrinsic size before a container size is available. m_intrinsicSize = containerSize(); } return m_page; }
void SVGImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp, blink::WebBlendMode blendMode) { if (!m_page) return; GraphicsContextStateSaver stateSaver(*context); context->setCompositeOperation(compositeOp, blendMode); context->clip(enclosingIntRect(dstRect)); bool compositingRequiresTransparencyLayer = compositeOp != CompositeSourceOver || blendMode != blink::WebBlendModeNormal; float opacity = context->getNormalizedAlpha() / 255.f; bool requiresTransparencyLayer = compositingRequiresTransparencyLayer || opacity < 1; if (requiresTransparencyLayer) { context->beginTransparencyLayer(opacity); if (compositingRequiresTransparencyLayer) context->setCompositeOperation(CompositeSourceOver, blink::WebBlendModeNormal); } FloatSize scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height()); // We can only draw the entire frame, clipped to the rect we want. So compute where the top left // of the image would be if we were drawing without clipping, and translate accordingly. FloatSize topLeftOffset(srcRect.location().x() * scale.width(), srcRect.location().y() * scale.height()); FloatPoint destOffset = dstRect.location() - topLeftOffset; context->translate(destOffset.x(), destOffset.y()); context->scale(scale); FrameView* view = frameView(); view->resize(containerSize()); if (view->needsLayout()) view->layout(); view->paint(context, enclosingIntRect(srcRect)); if (requiresTransparencyLayer) context->endLayer(); stateSaver.restore(); if (imageObserver()) imageObserver()->didDraw(this); }
void SVGImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace, CompositeOperator compositeOp, BlendMode) { if (!m_page) return; FrameView* view = frameView(); GraphicsContextStateSaver stateSaver(*context); context->setCompositeOperation(compositeOp); context->clip(enclosingIntRect(dstRect)); if (compositeOp != CompositeSourceOver) context->beginTransparencyLayer(1); FloatSize scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height()); // We can only draw the entire frame, clipped to the rect we want. So compute where the top left // of the image would be if we were drawing without clipping, and translate accordingly. FloatSize topLeftOffset(srcRect.location().x() * scale.width(), srcRect.location().y() * scale.height()); FloatPoint destOffset = dstRect.location() - topLeftOffset; context->translate(destOffset.x(), destOffset.y()); context->scale(scale); view->resize(containerSize()); if (view->needsLayout()) view->layout(); view->paint(context, IntRect(0, 0, view->width(), view->height())); if (compositeOp != CompositeSourceOver) context->endTransparencyLayer(); stateSaver.restore(); if (imageObserver()) imageObserver()->didDraw(this); }
// This function is used when the CSmileyContainer is created inside a dialog. void CSmileyContainer::ConstructFromResourceL(TResourceReader& aReader) { // Read the smiley mood from the resource file TBool isSmiling = (TBool) aReader.ReadInt8(); // Read the width of the smiley container from the resource file. TInt width = aReader.ReadInt16(); // Set the height of the container to be half its width TSize containerSize(width, width / 2); iSmiley1 = new (ELeave) CSmiley(isSmiling); iSmiley1->SetContainerWindowL(*this); iSmiley2 = new (ELeave) CSmiley(isSmiling); iSmiley2->SetContainerWindowL(*this); iSmiley1->SetFocus(ETrue); iSmiley1->SetObserver(this); iSmiley2->SetObserver(this); SetSize(containerSize); ActivateL(); }
const size_t size = SymbolGroupValue::sizeOf(innerType.c_str()); if (size == 0) return -1; return static_cast<int>((lastPtr - firstPtr) / size); } } return -1; } // Return size of container or -1 int containerSize(KnownType kt, SymbolGroupNode *n, const SymbolGroupValueContext &ctx) { QTC_TRACE_IN if ((kt & KT_ContainerType) == 0) return -1; const int ct = containerSize(kt, SymbolGroupValue(n, ctx)); QTC_TRACE_OUT return ct; } /*! Determine size of containers \ingroup qtcreatorcdbext */ int containerSize(KnownType kt, const SymbolGroupValue &v) { switch (kt) { case KT_QStringList: if (const SymbolGroupValue base = v[unsigned(0)]) return containerSize(KT_QList, base); break; case KT_QList: if (const SymbolGroupValue dV = v["d"]) { if (const SymbolGroupValue beginV = dV["begin"]) {
bool SVGImage::dataChanged(bool allDataReceived) { TRACE_EVENT0("blink", "SVGImage::dataChanged"); // Don't do anything if is an empty image. if (!data()->size()) return true; if (allDataReceived) { // SVGImage will fire events (and the default C++ handlers run) but doesn't // actually allow script to run so it's fine to call into it. We allow this // since it means an SVG data url can synchronously load like other image // types. EventDispatchForbiddenScope::AllowUserAgentEvents allowUserAgentEvents; DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<FrameLoaderClient>, dummyFrameLoaderClient, (EmptyFrameLoaderClient::create())); if (m_page) { toLocalFrame(m_page->mainFrame())->loader().load(FrameLoadRequest(0, blankURL(), SubstituteData(data(), AtomicString("image/svg+xml", AtomicString::ConstructFromLiteral), AtomicString("UTF-8", AtomicString::ConstructFromLiteral), KURL(), ForceSynchronousLoad))); return true; } Page::PageClients pageClients; fillWithEmptyClients(pageClients); m_chromeClient = SVGImageChromeClient::create(this); pageClients.chromeClient = m_chromeClient.get(); // FIXME: If this SVG ends up loading itself, we might leak the world. // The Cache code does not know about ImageResources holding Frames and // won't know to break the cycle. // This will become an issue when SVGImage will be able to load other // SVGImage objects, but we're safe now, because SVGImage can only be // loaded by a top-level document. OwnPtrWillBeRawPtr<Page> page; { TRACE_EVENT0("blink", "SVGImage::dataChanged::createPage"); page = Page::create(pageClients); page->settings().setScriptEnabled(false); page->settings().setPluginsEnabled(false); page->settings().setAcceleratedCompositingEnabled(false); // Because this page is detached, it can't get default font settings // from the embedder. Copy over font settings so we have sensible // defaults. These settings are fixed and will not update if changed. if (!Page::ordinaryPages().isEmpty()) { Settings& defaultSettings = (*Page::ordinaryPages().begin())->settings(); page->settings().genericFontFamilySettings() = defaultSettings.genericFontFamilySettings(); page->settings().setMinimumFontSize(defaultSettings.minimumFontSize()); page->settings().setMinimumLogicalFontSize(defaultSettings.minimumLogicalFontSize()); page->settings().setDefaultFontSize(defaultSettings.defaultFontSize()); page->settings().setDefaultFixedFontSize(defaultSettings.defaultFixedFontSize()); } } RefPtrWillBeRawPtr<LocalFrame> frame = nullptr; { TRACE_EVENT0("blink", "SVGImage::dataChanged::createFrame"); frame = LocalFrame::create(dummyFrameLoaderClient.get(), &page->frameHost(), 0); frame->setView(FrameView::create(frame.get())); frame->init(); } FrameLoader& loader = frame->loader(); loader.forceSandboxFlags(SandboxAll); frame->view()->setScrollbarsSuppressed(true); frame->view()->setCanHaveScrollbars(false); // SVG Images will always synthesize a viewBox, if it's not available, and thus never see scrollbars. frame->view()->setTransparent(true); // SVG Images are transparent. m_page = page.release(); TRACE_EVENT0("blink", "SVGImage::dataChanged::load"); loader.load(FrameLoadRequest(0, blankURL(), SubstituteData(data(), AtomicString("image/svg+xml", AtomicString::ConstructFromLiteral), AtomicString("UTF-8", AtomicString::ConstructFromLiteral), KURL(), ForceSynchronousLoad))); // Set the intrinsic size before a container size is available. m_intrinsicSize = containerSize(); } return m_page; }
void AdvancedGridLayout::computeLayout(NVGcontext *ctx, const Widget *widget, std::vector<int> *_grid) const { Vector2i fs_w = widget->fixedSize(); Vector2i containerSize( fs_w[0] ? fs_w[0] : widget->width(), fs_w[1] ? fs_w[1] : widget->height() ); Vector2i extra = Vector2i::Constant(2 * mMargin); if (dynamic_cast<const Window *>(widget)) extra[1] += widget->theme()->mWindowHeaderHeight - mMargin/2; containerSize -= extra; for (int axis=0; axis<2; ++axis) { std::vector<int> &grid = _grid[axis]; const std::vector<int> &sizes = axis == 0 ? mCols : mRows; const std::vector<float> &stretch = axis == 0 ? mColStretch : mRowStretch; grid = sizes; for (int phase = 0; phase < 2; ++phase) { for (auto pair : mAnchor) { const Widget *w = pair.first; if (!w->visible()) continue; const Anchor &anchor = pair.second; if ((anchor.size[axis] == 1) != (phase == 0)) continue; int ps = w->preferredSize(ctx)[axis], fs = w->fixedSize()[axis]; int targetSize = fs ? fs : ps; if (anchor.pos[axis] + anchor.size[axis] > (int) grid.size()) throw std::runtime_error( "Advanced grid layout: widget is out of bounds: " + (std::string) anchor); int currentSize = 0; float totalStretch = 0; for (int i = anchor.pos[axis]; i < anchor.pos[axis] + anchor.size[axis]; ++i) { if (sizes[i] == 0 && anchor.size[axis] == 1) grid[i] = std::max(grid[i], targetSize); currentSize += grid[i]; totalStretch += stretch[i]; } if (targetSize <= currentSize) continue; if (totalStretch == 0) throw std::runtime_error( "Advanced grid layout: no space to place widget: " + (std::string) anchor); float amt = (targetSize - currentSize) / totalStretch; for (int i = anchor.pos[axis]; i < anchor.pos[axis] + anchor.size[axis]; ++i) { grid[i] += (int) std::round(amt * stretch[i]); } } } int currentSize = std::accumulate(grid.begin(), grid.end(), 0); float totalStretch = std::accumulate(stretch.begin(), stretch.end(), 0.0f); if (currentSize >= containerSize[axis] || totalStretch == 0) continue; float amt = (containerSize[axis] - currentSize) / totalStretch; for (size_t i = 0; i<grid.size(); ++i) grid[i] += (int) std::round(amt * stretch[i]); } }
void GridLayout::performLayout(NVGcontext *ctx, Widget *widget) const { Vector2i fs_w = widget->fixedSize(); Vector2i containerSize( fs_w[0] ? fs_w[0] : widget->width(), fs_w[1] ? fs_w[1] : widget->height() ); /* Compute minimum row / column sizes */ std::vector<int> grid[2]; computeLayout(ctx, widget, grid); int dim[2] = { (int) grid[0].size(), (int) grid[1].size() }; Vector2i extra = Vector2i::Zero(); if (dynamic_cast<Window *>(widget)) extra[1] += widget->theme()->mWindowHeaderHeight - mMargin / 2; /* Strech to size provided by \c widget */ for (int i = 0; i < 2; i++) { int gridSize = 2 * mMargin + extra[i]; for (int s : grid[i]) { gridSize += s; if (i+1 < dim[i]) gridSize += mSpacing[i]; } if (gridSize < containerSize[i]) { /* Re-distribute remaining space evenly */ int gap = containerSize[i] - gridSize; int g = gap / dim[i]; int rest = gap - g * dim[i]; for (int j = 0; j < dim[i]; ++j) grid[i][j] += g; for (int j = 0; rest > 0 && j < dim[i]; --rest, ++j) grid[i][j] += 1; } } int axis1 = (int) mOrientation, axis2 = (axis1 + 1) % 2; Vector2i start = Vector2i::Constant(mMargin) + extra; size_t numChildren = widget->children().size(); size_t child = 0; Vector2i pos = start; for (int i2 = 0; i2 < dim[axis2]; i2++) { pos[axis1] = start[axis1]; for (int i1 = 0; i1 < dim[axis1]; i1++) { Widget *w = nullptr; do { if (child >= numChildren) return; w = widget->children()[child++]; } while (!w->visible()); Vector2i ps = w->preferredSize(ctx); Vector2i fs = w->fixedSize(); Vector2i targetSize( fs[0] ? fs[0] : ps[0], fs[1] ? fs[1] : ps[1] ); Vector2i itemPos(pos); for (int j = 0; j < 2; j++) { int axis = (axis1 + j) % 2; int item = j == 0 ? i1 : i2; Alignment align = alignment(axis, item); switch (align) { case Alignment::Minimum: break; case Alignment::Middle: itemPos[axis] += (grid[axis][item] - targetSize[axis]) / 2; break; case Alignment::Maximum: itemPos[axis] += grid[axis][item] - targetSize[axis]; break; case Alignment::Fill: targetSize[axis] = fs[axis] ? fs[axis] : grid[axis][item]; break; } } w->setPosition(itemPos); w->setSize(targetSize); w->performLayout(ctx); pos[axis1] += grid[axis1][i1] + mSpacing[axis1]; } pos[axis2] += grid[axis2][i2] + mSpacing[axis2]; } }