public void Arrange(Document document)
        {
            var pageSize = document.Variable(PageVariables.Size);
            var margin   = document.Variable(PageVariables.Margin);
            var boxSize  = pageSize;

            boxSize.Height -= margin.Height;
            boxSize.Width  -= margin.Width;

            var startOffset      = new Position(margin.Left, margin.Top);
            var extraStartOffset = new Position(margin.Left, pageSize.Height - margin.Bottom);
            var contentArea      = new Rectangle(startOffset, boxSize);

            MeasuredDocumentPage?curPage = null;
            double curHeight             = boxSize.Height;

            var flexList     = new LinkedList <Measurement>();
            var measurements = new List <Measurement>(document.Measurements);

            // Stage one:
            // Add measurements to pages
            for (int i = 0; i < measurements.Count; i++)
            {
                var measurement = measurements[i];

                if (measurement.Element is PdfElement pdfElement)
                {
                    document.Pages.Add(new PdfDocumentPage(document, pdfElement));
                    // reseting the page so that following measurements start on a new page.
                    curPage = null;
                }
                else
                {
                    if (curPage == null)
                    {
                        curPage   = AddPage(document, pageSize, contentArea);
                        curHeight = boxSize.Height;
                    }

                    FitFlex(curPage, flexList, ref curHeight);

                    if (TryFitMeasurement(curPage, measurement, flexList, false, ref curHeight) == FitResult.AddPage)
                    {
                        var split = measurement.Element.Split(measurement, curHeight);

                        if (split.IsSplit)
                        {
                            curPage.Measurements.Add(split.Measurement);
                            if (split.Measurement.Element.Page == null)
                            {
                                split.Measurement.Element.Page = curPage;
                            }
                            measurements[i] = split.Measurement;
                            if (split.Next != null)
                            {
                                measurements.Insert(i + 1, split.Next);
                            }
                        }
                        else if (curHeight == boxSize.Height)
                        {
                            curPage.Measurements.Add(split.Source);
                            if (split.Source.Element.Page == null)
                            {
                                split.Source.Element.Page = curPage;
                            }
                        }

                        curHeight = boxSize.Height;
                        curPage   = AddPage(document, pageSize, contentArea);
                    }
                }
            }

            if (curPage != null)
            {
                // Add leftover flexible items (part of stage one)
                foreach (var m in flexList)
                {
                    m.Flexible = false;

                    if (TryFitMeasurement(curPage, m, flexList, false, ref curHeight) == FitResult.AddPage)
                    {
                        curHeight = boxSize.Height;
                        curPage   = AddPage(document, pageSize, contentArea);
                        TryFitMeasurement(curPage, m, flexList, false, ref curHeight);
                    }
                }
            }
            flexList.Clear();

            // Stage two:
            // Layout measurements on each page
            foreach (var page in document.Pages.OfType <MeasuredDocumentPage>())
            {
                var extras        = new List <Measurement>();
                var currentOffset = startOffset;
                var extraHeight   = 0.0;

                foreach (var measurement in page.Measurements)
                {
                    var accumulated = measurement.AccumulatedExtra;
                    extras.AddRange(accumulated.Subs);
                    extraHeight += accumulated.TotalSize.Height;
                }

                foreach (var measurement in page.Measurements)
                {
                    var size = measurement.TotalSize;

                    measurement.Position = currentOffset;
                    Realign(measurement, boxSize, pageSize, measurement.Element.Style.Get(StyleKeys.HorizontalAlignment));
                    measurement.Element.Arrange(measurement);

                    currentOffset.Y += size.Height;
                }

                var extraOffset = new Position(extraStartOffset.X, extraStartOffset.Y - extraHeight);

                // Add footnote bar
                if (extras.Count > 0)
                {
                    var line = new Line(Position.Zero, new Position(boxSize.Width / 2.5, 0));
                    var path = new PathElement(line)
                    {
                        Document = document,
                        Page     = page,
                        Stroke   = Colors.Black,
                        Fill     = Colors.Black
                    };
                    var pathMeasurement = path.Measure(boxSize);
                    pathMeasurement.Position = extraOffset;
                    path.Arrange(pathMeasurement);
                    page.Measurements.Add(pathMeasurement);
                }

                foreach (var extra in extras)
                {
                    var size = extra.TotalSize;

                    extra.Position = extraOffset;
                    Realign(extra, boxSize, pageSize, extra.Element.Style.Get(StyleKeys.HorizontalAlignment));
                    extra.Element.Arrange(extra);

                    extraOffset.Y += size.Height;
                }

                // Set number at the end of the page layouting
                // so that any number changing elements can take effect
                page.Number = document.PageNumbering.Next();
                page.AddPageItems();
            }
        }