Exemple #1
0
MainPane::MainPane()
{
    sf::Vector2f targetSize(1280 - 200, 720);
//    box.setFillColor(sf::Color(255, 133, 100));
//    texture.loadFromFile("mango.png");
//    mango.setTexture(texture);

//    mango.setScale(0.5, 0.5);
//    mango.setScale(
//            1,
//            targetSize.y / mango.getLocalBounds().height);

//    mango.setOrigin(mango.getLocalBounds().width, mango.getLocalBounds().height);
    sf::FloatRect mangoRect = mango.getLocalBounds();
    mango.setOrigin(mangoRect.left + mangoRect.width/2.0f,
            0);
    mango.setPosition(targetSize.x/2.0f,0);
//    mango.setPosition(0, 0);


    bgArea.setSize(sf::Vector2f(200, 720-200));
    bgArea.setPosition(1280-200, 0);
    bgArea.setFillColor(sf::Color(255, 255, 255, 128));

    messageArea.setSize(sf::Vector2f(bgArea.getSize().x - 5, bgArea.getSize().y - 5));
    messageArea.setPosition(bgArea.getPosition().x + 3, bgArea.getPosition().y + 3);
    messageArea.setFillColor(sf::Color(255, 255, 255, 128));
}
Vector2i BoxLayout::preferredSize(NVGcontext *ctx, const Widget *widget) const {
    Vector2i size = Vector2i::Constant(2*mMargin);

    if (dynamic_cast<const Window *>(widget))
        size[1] += widget->theme()->mWindowHeaderHeight - mMargin/2;

    bool first = true;
    int axis1 = (int) mOrientation, axis2 = ((int) mOrientation + 1)%2;
    for (auto w : widget->children()) {
        if (!w->visible())
            continue;
        if (first)
            first = false;
        else
            size[axis1] += mSpacing;

        Vector2i ps = w->preferredSize(ctx), fs = w->fixedSize();
        Vector2i targetSize(
            fs[0] ? fs[0] : ps[0],
            fs[1] ? fs[1] : ps[1]
        );

        size[axis1] += targetSize[axis1];
        size[axis2] = std::max(size[axis2], targetSize[axis2] + 2*mMargin);
        first = false;
    }
    return size;
}
void GridLayout::computeLayout(NVGcontext *ctx, const Widget *widget, std::vector<int> *grid) const {
    int axis1 = (int) mOrientation, axis2 = (axis1 + 1) % 2;
    size_t numChildren = widget->children().size(), visibleChildren = 0;
    for (auto w : widget->children())
        visibleChildren += w->visible() ? 1 : 0;

    Vector2i dim;
    dim[axis1] = mResolution;
    dim[axis2] = (int) ((visibleChildren + mResolution - 1) / mResolution);

    grid[axis1].clear(); grid[axis1].resize(dim[axis1], 0);
    grid[axis2].clear(); grid[axis2].resize(dim[axis2], 0);

    size_t child = 0;
    for (int i2 = 0; i2 < dim[axis2]; i2++) {
        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]
            );

            grid[axis1][i1] = std::max(grid[axis1][i1], targetSize[axis1]);
            grid[axis2][i2] = std::max(grid[axis2][i2], targetSize[axis2]);
        }
    }
}
Vector2i GroupLayout::preferredSize(NVGcontext *ctx, const Widget *widget) const {
    int height = mMargin, width = 2*mMargin;

    const Window *window = dynamic_cast<const Window *>(widget);
    if (window && !window->title().empty())
        height += widget->theme()->mWindowHeaderHeight - mMargin/2;

    bool first = true, indent = false;
    for (auto c : widget->children()) {
        if (!c->visible())
            continue;
        const Label *label = dynamic_cast<const Label *>(c);
        if (!first)
            height += (label == nullptr) ? mSpacing : mGroupSpacing;
        first = false;

        Vector2i ps = c->preferredSize(ctx), fs = c->fixedSize();
        Vector2i targetSize(
            fs[0] ? fs[0] : ps[0],
            fs[1] ? fs[1] : ps[1]
        );

        bool indentCur = indent && label == nullptr;
        height += targetSize.y();
        width = std::max(width, targetSize.x() + 2*mMargin + (indentCur ? mGroupIndent : 0));

        if (label)
            indent = !label->caption().empty();
    }
    height += mMargin;
    return Vector2i(width, height);
}
void GraphicsItemResizer::setTargetSize(const QSizeF &size)
{
    if (size == targetSize())
    {
        return;
    }
    updateDimensions(size);
}
Exemple #6
0
FreqFirstCharMap::FreqFirstCharMap(const CharFreqMap& charFreqMap, uint minCount)
	: ArrayCharMap(charFreqMap.getRangeCountOverMin(minCount), 0, charFreqMap.getMinChar(), charFreqMap.getMaxChar())
{
////mCharToIndexMem = (uint *) malloc(sDomainSize*sizeof(uint));
	mCharToIndexMem = new uint[charFreqMap.sDomainSize];
	mCharToIndexPtr = mCharToIndexMem - charFreqMap.sBegChar;
	memset(mCharToIndexMem, charFreqMap.getRangeCount(), charFreqMap.sDomainSize*sizeof(uint));
	charFreqMap.initTableFrequencyOrder(mCharToIndexPtr, targetSize());
}
void GraphicsItemResizer::updateTargetRect(const QRectF &rect)
{
    if (rect.size() == targetSize())
    {
        return;
    }
    updateDimensions(rect.size());
    emit targetRectChanged(rect);
}
void WindowCreateThing::init(sf::RenderWindow &window) {

    rectTitle.setSize(sf::Vector2f(window.getSize().x*0.45, window.getSize().y*0.07));
    rectTitle.setPosition(sf::Vector2f(window.getSize().x/2-(rectTitle.getSize().x/2), window.getSize().x/4-(rectTitle.getSize().y/2)));
    rectTitle.setFillColor(sf::Color(158, 158, 158));
    rectTitle.setOutlineColor(sf::Color::Black);
    rectTitle.setOutlineThickness(1.f);

    rectMain.setSize(sf::Vector2f(window.getSize().x*0.45,window.getSize().y*0.45));
    rectMain.setPosition(sf::Vector2f(rectTitle.getPosition().x, rectTitle.getPosition().y+rectTitle.getSize().y));
    rectMain.setFillColor(sf::Color::White);
    rectMain.setOutlineColor(sf::Color::Black);
    rectMain.setOutlineThickness(1.f);

    load();


    starting_position = sf::Mouse::getPosition(window);



    textTitle.setFont(font);
    textTitle.setString("CreateThings.txt");
    textTitle.setCharacterSize(24);
    textTitle.setColor(sf::Color::White);
    textTitle.setPosition(sf::Vector2f(rectTitle.getPosition().x+rectTitle.getSize().x*0.3, rectTitle.getPosition().y+rectTitle.getSize().y*0.1));
    //textTitle.setPosition(sf::Vector2f(400,10));

    textClose.setFont(font);
    textClose.setString("X");
    textClose.setStyle(sf::Text::Bold);
    textClose.setCharacterSize(35);
    textClose.setColor(sf::Color::White);
    textClose.setPosition(sf::Vector2f(rectTitle.getPosition().x+rectTitle.getSize().x-30, rectTitle.getPosition().y+rectTitle.getSize().y*0.05));


    ///// FOLDER ICONE
    textureFolder.setSmooth(true);
    spriteFodler.setTexture(textureFolder);
    sf::Vector2f targetSize(25.0f, 25.0f);
    spriteFodler.setScale(
        targetSize.x / spriteFodler.getLocalBounds().width,
        targetSize.y / spriteFodler.getLocalBounds().height);
    spriteFodler.setPosition(sf::Vector2f(textTitle.getPosition().x-targetSize.x, textTitle.getPosition().y));




    ///// CLOSE ICONE
    /*textureClose.setSmooth(true);
    spriteClose.setTexture(textureClose);
    sf::Vector2f targetSize2(window.getSize().y*0.07, window.getSize().y*0.07);
    spriteClose.setScale(
        targetSize2.x / spriteClose.getLocalBounds().width,
        targetSize2.y / spriteClose.getLocalBounds().height);
    spriteClose.setPosition(rectTitle.getPosition().x+rectTitle.getSize().x-targetSize2.x, rectTitle.getPosition().y);*/
}
IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, const IntSize& transformOffset, const IntPoint& popupInitialCoordinate)
{
    // Reset the max width and height to their default values, they will be
    // recomputed below if necessary.
    m_listBox->setMaxHeight(PopupListBox::defaultMaxHeight);
    m_listBox->setMaxWidth(std::numeric_limits<int>::max());

    // Lay everything out to figure out our preferred size, then tell the view's
    // WidgetClient about it. It should assign us a client.
    m_listBox->layout();
    fitToListBox();
    bool isRTL = this->isRTL();

    // Compute the starting x-axis for a normal RTL or right-aligned LTR
    // dropdown. For those, the right edge of dropdown box should be aligned
    // with the right edge of <select>/<input> element box, and the dropdown box
    // should be expanded to the left if more space is needed.
    // m_originalFrameRect.width() is the width of the target <select>/<input>
    // element.
    int rtlOffset = m_controlPosition.p2().x() - m_controlPosition.p1().x() - (m_listBox->width() + borderSize * 2);
    int rightOffset = isRTL ? rtlOffset : 0;

    // Compute the y-axis offset between the bottom left and bottom right
    // points. If the <select>/<input> is transformed, they are not the same.
    int verticalOffset = - m_controlPosition.p4().y() + m_controlPosition.p3().y();
    int verticalForRTLOffset = isRTL ? verticalOffset : 0;

    // Assume m_listBox size is already calculated.
    IntSize targetSize(m_listBox->width() + borderSize * 2, m_listBox->height() + borderSize * 2);

    IntRect widgetRectInScreen;
    // If the popup would extend past the bottom of the screen, open upwards
    // instead.
    FloatRect screen = screenAvailableRect(m_frameView.get());
    // Use popupInitialCoordinate.x() + rightOffset because RTL position
    // needs to be considered.
    float pageScaleFactor = m_frameView->frame().page()->pageScaleFactor();
    int popupX = round((popupInitialCoordinate.x() + rightOffset) * pageScaleFactor);
    int popupY = round((popupInitialCoordinate.y() + verticalForRTLOffset) * pageScaleFactor);
    widgetRectInScreen = chromeClient().rootViewToScreen(IntRect(popupX, popupY, targetSize.width(), targetSize.height()));

    // If we have multiple screens and the browser rect is in one screen, we
    // have to clip the window width to the screen width.
    // When clipping, we also need to set a maximum width for the list box.
    FloatRect windowRect = chromeClient().windowRect();

    bool needToResizeView = false;
    widgetRectInScreen = layoutAndCalculateWidgetRectInternal(widgetRectInScreen, targetControlHeight, windowRect, screen, isRTL, rtlOffset, verticalOffset, transformOffset, m_listBox.get(), needToResizeView);
    if (needToResizeView)
        fitToListBox();

    return widgetRectInScreen;
}
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];
    }
}
Exemple #11
0
status_t DataConverter::convert(const sp<MediaCodecBuffer> &source, sp<MediaCodecBuffer> &target) {
    CHECK(source->base() != target->base());
    size_t size = targetSize(source->size());
    status_t err = OK;
    if (size > target->capacity()) {
        ALOGE("data size (%zu) is greater than buffer capacity (%zu)",
                size,          // this is the data received/to be converted
                target->capacity()); // this is out buffer size
        err = FAILED_TRANSACTION;
    } else {
        err = safeConvert(source, target);
    }
    target->setRange(0, err == OK ? size : 0);
    return err;
}
Exemple #12
0
IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, const IntPoint& popupInitialCoordinate)
{
    // Reset the max width and height to their default values, they will be recomputed below
    // if necessary.
    m_listBox->setMaxHeight(kMaxHeight);
    m_listBox->setMaxWidth(std::numeric_limits<int>::max());

    // Lay everything out to figure out our preferred size, then tell the view's
    // WidgetClient about it. It should assign us a client.
    int rtlOffset = layoutAndGetRTLOffset();
    bool isRTL = this->isRTL();
    int rightOffset = isRTL ? rtlOffset : 0;

    // Assume m_listBox size is already calculated.
    IntSize targetSize(m_listBox->width() + kBorderSize * 2,
                       m_listBox->height() + kBorderSize * 2);

    IntRect widgetRectInScreen;
    ChromeClientChromium* chromeClient = chromeClientChromium();
    if (chromeClient) {
        // If the popup would extend past the bottom of the screen, open upwards
        // instead.
        FloatRect screen = screenAvailableRect(m_frameView.get());
        // Use popupInitialCoordinate.x() + rightOffset because RTL position
        // needs to be considered.
        widgetRectInScreen = chromeClient->rootViewToScreen(IntRect(popupInitialCoordinate.x() + rightOffset, popupInitialCoordinate.y(), targetSize.width(), targetSize.height()));

        // If we have multiple screens and the browser rect is in one screen, we have
        // to clip the window width to the screen width.
        // When clipping, we also need to set a maximum width for the list box.
        FloatRect windowRect = chromeClient->windowRect();

        bool needToResizeView = false;
        widgetRectInScreen = layoutAndCalculateWidgetRectInternal(widgetRectInScreen, targetControlHeight, windowRect, screen, isRTL, rtlOffset, m_listBox.get(), needToResizeView);
        if (needToResizeView)
            fitToListBox();
    }

    return widgetRectInScreen;
}
void GroupLayout::performLayout(NVGcontext *ctx, Widget *widget) const {
    int height = mMargin, availableWidth =
        (widget->fixedWidth() ? widget->fixedWidth() : widget->width()) - 2*mMargin;

    const Window *window = dynamic_cast<const Window *>(widget);
    if (window && !window->title().empty())
        height += widget->theme()->mWindowHeaderHeight - mMargin/2;

    bool first = true, indent = false;
    for (auto c : widget->children()) {
        if (!c->visible())
            continue;
        const Label *label = dynamic_cast<const Label *>(c);
        if (!first)
            height += (label == nullptr) ? mSpacing : mGroupSpacing;
        first = false;

        bool indentCur = indent && label == nullptr;
        Vector2i ps = Vector2i(availableWidth - (indentCur ? mGroupIndent : 0),
                               c->preferredSize(ctx).y());
        Vector2i fs = c->fixedSize();

        Vector2i targetSize(
            fs[0] ? fs[0] : ps[0],
            fs[1] ? fs[1] : ps[1]
        );

        c->setPosition(Vector2i(mMargin + (indentCur ? mGroupIndent : 0), height));
        c->setSize(targetSize);
        c->performLayout(ctx);

        height += targetSize.y();

        if (label)
            indent = !label->caption().empty();
    }
}
Exemple #14
0
int main(int argc, char * argv[])
{
	if(argc < 2)
	{
		showUsage();
	}

	bool inv = false;
	for(int i=1; i<argc-1; ++i)
	{
		if(strcmp(argv[i], "-inv") == 0)
		{
			inv = true;
			printf(" Inversing option activated...\n");
			continue;
		}
		if(argc > 3)
		{
			showUsage();
			printf(" Not recognized option: \"%s\"\n", argv[i]);
		}
	}

	std::string path, pathRight;

	if(argc == 3 && !inv)
	{
		//two paths
		path = argv[1];
		pathRight = argv[2];

		printf(" Path left = %s\n", path.c_str());
		printf(" Path right = %s\n", pathRight.c_str());
	}
	else
	{
		path = argv[argc-1];
		printf(" Path = %s\n", path.c_str());
	}

	UDirectory dir(path, "jpg bmp png tiff jpeg");
	UDirectory dirRight(pathRight, "jpg bmp png tiff jpeg");
	if(!dir.isValid() || (!pathRight.empty() && !dirRight.isValid()))
	{
		printf("Path invalid!\n");
		exit(-1);
	}

	std::string targetDirectory = path+"_joined";
	UDirectory::makeDir(targetDirectory);
	printf(" Creating directory \"%s\"\n", targetDirectory.c_str());


	std::string fileNameA = dir.getNextFilePath();
	std::string fileNameB;
	if(dirRight.isValid())
	{
		fileNameB = dirRight.getNextFilePath();
	}
	else
	{
		fileNameB = dir.getNextFilePath();
	}

	int i=1;
	while(!fileNameA.empty() && !fileNameB.empty())
	{
		if(inv)
		{
			std::string tmp = fileNameA;
			fileNameA = fileNameB;
			fileNameB = tmp;
		}

		std::string ext = UFile::getExtension(fileNameA);

		std::string targetFilePath = targetDirectory+UDirectory::separator()+uNumber2Str(i++)+"."+ext;

		cv::Mat imageA = cv::imread(fileNameA.c_str());
		cv::Mat imageB = cv::imread(fileNameB.c_str());

		fileNameA.clear();
		fileNameB.clear();

		if(!imageA.empty() && !imageB.empty())
		{
			cv::Size sizeA = imageA.size();
			cv::Size sizeB = imageB.size();
			cv::Size targetSize(0,0);
			targetSize.width = sizeA.width + sizeB.width;
			targetSize.height = sizeA.height > sizeB.height ? sizeA.height : sizeB.height;
			cv::Mat targetImage(targetSize, imageA.type());

			cv::Mat roiA(targetImage, cv::Rect( 0, 0, sizeA.width, sizeA.height ));
			imageA.copyTo(roiA);
			cv::Mat roiB( targetImage, cvRect( sizeA.width, 0, sizeB.width, sizeB.height ) );
			imageB.copyTo(roiB);

			if(!cv::imwrite(targetFilePath.c_str(), targetImage))
			{
				printf("Error : saving to \"%s\" goes wrong...\n", targetFilePath.c_str());
			}
			else
			{
				printf("Saved \"%s\" \n", targetFilePath.c_str());
			}

			fileNameA = dir.getNextFilePath();
			if(dirRight.isValid())
			{
				fileNameB = dirRight.getNextFilePath();
			}
			else
			{
				fileNameB = dir.getNextFilePath();
			}
		}
		else
		{
			printf("Error: loading images failed!\n");
		}
	}
	printf("%d files processed\n", i-1);

	return 0;
}
Exemple #15
0
IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, const IntPoint& popupInitialCoordinate)
{
    // Reset the max width and height to their default values, they will be recomputed below
    // if necessary.
    m_listBox->setMaxHeight(kMaxHeight);
    m_listBox->setMaxWidth(std::numeric_limits<int>::max());

    // Lay everything out to figure out our preferred size, then tell the view's
    // WidgetClient about it. It should assign us a client.
    int rtlOffset = layoutAndGetRTLOffset();
    bool isRTL = this->isRTL();
    int rightOffset = isRTL ? rtlOffset : 0;

    // Assume m_listBox size is already calculated.
    IntSize targetSize(m_listBox->width() + kBorderSize * 2,
                       m_listBox->height() + kBorderSize * 2);

    IntRect widgetRect;
    ChromeClientChromium* chromeClient = chromeClientChromium();
    if (chromeClient) {
        // If the popup would extend past the bottom of the screen, open upwards
        // instead.
        FloatRect screen = screenAvailableRect(m_frameView.get());
        // Use popupInitialCoordinate.x() + rightOffset because RTL position
        // needs to be considered.
        widgetRect = chromeClient->rootViewToScreen(IntRect(popupInitialCoordinate.x() + rightOffset, popupInitialCoordinate.y(), targetSize.width(), targetSize.height()));

        // If we have multiple screens and the browser rect is in one screen, we have
        // to clip the window width to the screen width.
        // When clipping, we also need to set a maximum width for the list box.
        FloatRect windowRect = chromeClient->windowRect();
        if (windowRect.x() >= screen.x() && windowRect.maxX() <= screen.maxX() && (widgetRect.x() < screen.x() || widgetRect.maxX() > screen.maxX())) {
            // First, inverse the popup alignment if it does not fit the screen - this might fix things (or make them better).
            IntRect inverseWidgetRect = chromeClient->rootViewToScreen(IntRect(popupInitialCoordinate.x() + (isRTL ? 0 : rtlOffset), popupInitialCoordinate.y(), targetSize.width(), targetSize.height()));
            IntRect enclosingScreen = enclosingIntRect(screen);
            unsigned originalCutoff = max(enclosingScreen.x() - widgetRect.x(), 0) + max(widgetRect.maxX() - enclosingScreen.maxX(), 0);
            unsigned inverseCutoff = max(enclosingScreen.x() - inverseWidgetRect.x(), 0) + max(inverseWidgetRect.maxX() - enclosingScreen.maxX(), 0);

            // Accept the inverse popup alignment if the trimmed content gets shorter than that in the original alignment case.
            if (inverseCutoff < originalCutoff)
                widgetRect = inverseWidgetRect;

            if (widgetRect.x() < screen.x()) {
                unsigned widgetRight = widgetRect.maxX();
                widgetRect.setWidth(widgetRect.maxX() - screen.x());
                widgetRect.setX(widgetRight - widgetRect.width());
                listBox()->setMaxWidthAndLayout(max(widgetRect.width() - kBorderSize * 2, 0));
            } else if (widgetRect.maxX() > screen.maxX()) {
                widgetRect.setWidth(screen.maxX() - widgetRect.x());
                listBox()->setMaxWidthAndLayout(max(widgetRect.width() - kBorderSize * 2, 0));
            }
        }

        // Calculate Y axis size.
        if (widgetRect.maxY() > static_cast<int>(screen.maxY())) {
            if (widgetRect.y() - widgetRect.height() - targetControlHeight > 0) {
                // There is enough room to open upwards.
                widgetRect.move(0, -(widgetRect.height() + targetControlHeight));
            } else {
                // Figure whether upwards or downwards has more room and set the
                // maximum number of items.
                int spaceAbove = widgetRect.y() - targetControlHeight;
                int spaceBelow = screen.maxY() - widgetRect.y();
                if (spaceAbove > spaceBelow)
                    m_listBox->setMaxHeight(spaceAbove);
                else
                    m_listBox->setMaxHeight(spaceBelow);
                layoutAndGetRTLOffset();
                // Our height has changed, so recompute only Y axis of widgetRect.
                // We don't have to recompute X axis, so we only replace Y axis
                // in widgetRect.
                IntRect frameInScreen = chromeClient->rootViewToScreen(frameRect());
                widgetRect.setY(frameInScreen.y());
                widgetRect.setHeight(frameInScreen.height());
                // And move upwards if necessary.
                if (spaceAbove > spaceBelow)
                    widgetRect.move(0, -(widgetRect.height() + targetControlHeight));
            }
        }
    }
    return widgetRect;
}
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];
    }
}