Skip to content

Commit

Permalink
Refactor pagination logic
Browse files Browse the repository at this point in the history
  • Loading branch information
sammycage committed Jun 14, 2024
1 parent 4304970 commit f6efc11
Show file tree
Hide file tree
Showing 12 changed files with 87 additions and 46 deletions.
3 changes: 2 additions & 1 deletion include/plutobook.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ typedef enum _plutobook_media_type {

typedef struct _plutobook plutobook_t;

PLUTOBOOK_API plutobook_t* plutobook_create(plutobook_page_size_t size, plutobook_page_margins_t margins, plutobook_media_type_t media);
PLUTOBOOK_API plutobook_t* plutobook_create(plutobook_page_size_t size, plutobook_page_margins_t margins, plutobook_media_type_t media, float scale);
PLUTOBOOK_API void plutobook_destroy(plutobook_t* book);
PLUTOBOOK_API void plutobook_clear_content(plutobook_t* book);

Expand All @@ -292,6 +292,7 @@ PLUTOBOOK_API plutobook_page_size_t plutobook_get_page_size(const plutobook_t* b
PLUTOBOOK_API plutobook_page_margins_t plutobook_get_page_margins(const plutobook_t* book);
PLUTOBOOK_API plutobook_page_size_t plutobook_get_page_size_at(const plutobook_t* book, unsigned int index);
PLUTOBOOK_API plutobook_media_type_t plutobook_get_media_type(const plutobook_t* book);
PLUTOBOOK_API float plutobook_get_page_scale(const plutobook_t* book);
PLUTOBOOK_API unsigned int plutobook_get_page_count(const plutobook_t* book);

PLUTOBOOK_API plutobook_status_t plutobook_load_url(plutobook_t* book, const char* url, const char* user_style, const char* user_script);
Expand Down
10 changes: 9 additions & 1 deletion include/plutobook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,9 @@ class PLUTOBOOK_API Book {
* @param size
* @param margins
* @param media
* @param scale
*/
Book(const PageSize& size, const PageMargins& margins = PageMargins::Normal, MediaType media = MediaType::Print);
Book(const PageSize& size, const PageMargins& margins = PageMargins::Normal, MediaType media = MediaType::Print, float scale = 0);

/**
* @brief ~Book
Expand Down Expand Up @@ -664,6 +665,12 @@ class PLUTOBOOK_API Book {
*/
MediaType mediaType() const { return m_mediaType; }

/**
* @brief pageCount
* @return
*/
uint32_t pageScale() const { return m_pageScale; }

/**
* @brief pageCount
* @return
Expand Down Expand Up @@ -902,6 +909,7 @@ class PLUTOBOOK_API Book {
PageSize m_pageSize;
PageMargins m_pageMargins;
MediaType m_mediaType;
float m_pageScale{0};

mutable bool m_needsBuild{true};
mutable bool m_needsLayout{true};
Expand Down
4 changes: 2 additions & 2 deletions source/document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -825,12 +825,12 @@ void Document::renderPage(GraphicsContext& context, uint32_t pageIndex)
if(pageIndex >= m_pages.size())
return;
const auto& page = m_pages[pageIndex];
Rect pageRect(0, page->pageTop(), (page->width() - page->marginWidth()) / page->pageScale(), page->pageBottom() - page->pageTop());
Rect pageRect(0, page->pageTop(), box()->pageWidth(), page->pageBottom() - page->pageTop());
if(pageRect.isEmpty())
return;
context.save();
context.translate(page->marginLeft(), page->marginTop());
context.scale(page->pageScale(), page->pageScale());
context.scale(box()->pageScale(), box()->pageScale());
context.translate(-pageRect.x, -pageRect.y);
context.clipRect(pageRect);
box()->layer()->paint(context, pageRect);
Expand Down
3 changes: 2 additions & 1 deletion source/layout/blockbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1482,7 +1482,8 @@ void BlockFlowBox::paginate(PageBuilder& builder, float top) const
} else {
auto child = firstBoxFrame();
while(child) {
child->paginate(builder, adjustedTop);
if(!child->isFloatingOrPositioned())
child->paginate(builder, adjustedTop);
child = child->nextBoxFrame();
}
}
Expand Down
35 changes: 32 additions & 3 deletions source/layout/boxview.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "boxview.h"
#include "boxlayer.h"
#include "document.h"
#include "plutobook.hpp"

namespace plutobook {

Expand All @@ -9,22 +10,50 @@ BoxView::BoxView(Document* document, const RefPtr<BoxStyle>& style)
{
}

bool BoxView::isPrintMedia() const
{
if(auto book = document()->book())
return book->mediaType() == MediaType::Print;
return false;
}

void BoxView::computeWidth(float& x, float& width, float& marginLeft, float& marginRight) const
{
width = document()->viewportWidth();
width = pageWidth();
}

void BoxView::computeHeight(float& y, float& height, float& marginTop, float& marginBottom) const
{
height = document()->viewportHeight();
height = pageHeight();
}

void BoxView::layout()
void BoxView::layoutContents()
{
BlockFlowBox::layout();
layer()->layout();
}

void BoxView::layout()
{
auto pageScale = isPrintMedia() ? document()->book()->pageScale() : 1.f;
m_pageWidth = document()->viewportWidth();
m_pageHeight = document()->viewportHeight();
m_pageScale = 1.f;
if(pageScale > 0.f && isPrintMedia()) {
m_pageScale = pageScale / 100.f;
m_pageWidth /= m_pageScale;
m_pageHeight /= m_pageScale;
}

layoutContents();
if(pageScale <= 0.f && isPrintMedia() && m_pageWidth < document()->width()) {
m_pageScale = m_pageWidth / document()->width();
m_pageWidth /= m_pageScale;
m_pageHeight /= m_pageScale;
layoutContents();
}
}

void BoxView::build()
{
m_backgroundStyle = document()->rootStyle();
Expand Down
10 changes: 10 additions & 0 deletions source/layout/boxview.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,25 @@ class BoxView final : public BlockFlowBox {
bool requiresLayer() const final { return true; }
BoxStyle* backgroundStyle() const { return m_backgroundStyle; }

float pageWidth() const { return m_pageWidth; }
float pageHeight() const { return m_pageHeight; }
float pageScale() const { return m_pageScale; }

bool isPrintMedia() const;

void computeWidth(float& x, float& width, float& marginLeft, float& marginRight) const final;
void computeHeight(float& y, float& height, float& marginTop, float& marginBottom) const final;
void layoutContents();
void layout() final;
void build() final;

const char* name() const final { return "BoxView"; }

private:
BoxStyle* m_backgroundStyle{nullptr};
float m_pageWidth{0};
float m_pageHeight{0};
float m_pageScale{1};
};

template<>
Expand Down
5 changes: 4 additions & 1 deletion source/layout/linelayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1687,12 +1687,15 @@ void LineLayout::paint(const PaintInfo& info, const Point& offset, PaintPhase ph

void LineLayout::paginate(PageBuilder& builder, float top) const
{
float prevLineBottom = 0.f;
for(auto& line : m_lines) {
auto adjustedTop = top + line->lineTop();
builder.addPageUntil(m_block, adjustedTop);
if(!builder.canFitOnPage(top + line->lineBottom())) {
builder.setPageBreakAt(adjustedTop);
builder.setPageBreakAt(top + prevLineBottom);
}

prevLineBottom = line->lineBottom();
}
}

Expand Down
31 changes: 13 additions & 18 deletions source/layout/pagebox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ std::unique_ptr<PageBox> PageBox::create(const RefPtr<BoxStyle>& style, const Gl
return std::unique_ptr<PageBox>(new (style->heap()) PageBox(style, pageName, pageIndex));
}

const PageSize& PageBox::pageSize() const
{
return document()->book()->pageSize();
}

void PageBox::updateOverflowRect()
{
BlockBox::updateOverflowRect();
Expand All @@ -23,24 +28,18 @@ void PageBox::computePreferredWidths(float& minWidth, float& maxWidth) const

void PageBox::computeWidth(float& x, float& width, float& marginLeft, float& marginRight) const
{
auto marginLeftLength = style()->marginLeft();
auto marginRightLength = style()->marginRight();

const auto& deviceMargins = document()->book()->pageMargins();
marginLeft = marginLeftLength.isAuto() ? deviceMargins.left() / units::px : marginLeftLength.calcMin(m_pageSize.width() / units::px);
marginRight = marginRightLength.isAuto() ? deviceMargins.right() / units::px : marginRightLength.calcMin(m_pageSize.width() / units::px);
width = m_pageSize.width() / units::px;
auto book = document()->book();
width = book->pageSize().height() / units::px;
marginLeft = book->pageMargins().left() / units::px;
marginRight = book->pageMargins().right() / units::px;
}

void PageBox::computeHeight(float& y, float& height, float& marginTop, float& marginBottom) const
{
auto marginTopLength = style()->marginTop();
auto marginBottomLength = style()->marginBottom();

const auto& deviceMargins = document()->book()->pageMargins();
marginTop = marginTopLength.isAuto() ? deviceMargins.top() / units::px : marginTopLength.calcMin(m_pageSize.height() / units::px);
marginBottom = marginBottomLength.isAuto() ? deviceMargins.bottom() / units::px : marginBottomLength.calcMin(m_pageSize.height() / units::px);
height = m_pageSize.height() / units::px;
auto book = document()->book();
height = book->pageSize().height() / units::px;
marginTop = book->pageMargins().top() / units::px;
marginBottom = book->pageMargins().bottom() / units::px;
}

void PageBox::layout()
Expand All @@ -51,10 +50,6 @@ void PageBox::layout()

void PageBox::build()
{
const auto& deviceSize = document()->book()->pageSize();
auto pageSize = style()->getPageSize(deviceSize);
m_pageSize.setWidth(std::max(1.f, pageSize.width()));
m_pageSize.setHeight(std::max(1.f, pageSize.height()));
BlockBox::build();
}

Expand Down
6 changes: 1 addition & 5 deletions source/layout/pagebox.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,15 @@ class PageBox final : public BlockBox {

bool isPageBox() const final { return true; }
bool requiresLayer() const final { return false; }
const PageSize& pageSize() const { return m_pageSize; }
const GlobalString& pageName() const { return m_pageName; }
uint32_t pageIndex() const { return m_pageIndex; }
const PageSize& pageSize() const;

float pageTop() const { return m_pageTop; }
float pageBottom() const { return m_pageBottom; }
float pageScale() const { return m_pageScale; }

void setPageTop(float pageTop) { m_pageTop = pageTop; }
void setPageBottom(float pageBottom) { m_pageBottom = pageBottom; }
void setPageScale(float pageScale) { m_pageScale = pageScale; }

void updateOverflowRect() final;
void computePreferredWidths(float& minWidth, float& maxWidth) const final;
Expand All @@ -36,12 +34,10 @@ class PageBox final : public BlockBox {

private:
PageBox(const RefPtr<BoxStyle>& style, const GlobalString& pageName, uint32_t pageIndex);
PageSize m_pageSize;
GlobalString m_pageName;
uint32_t m_pageIndex;
float m_pageTop{0};
float m_pageBottom{0};
float m_pageScale{1};
};

template<>
Expand Down
14 changes: 3 additions & 11 deletions source/layout/pagebuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ void PageBuilder::addPageUntil(const BoxFrame* box, float top)
void PageBuilder::setPageBreakAt(float top)
{
if(m_currentPage && top > m_currentPage->pageTop()) {
m_currentPage->setPageBottom(std::floor(top));
m_currentPage->setPageBottom(top);
}
}

Expand All @@ -82,16 +82,8 @@ void PageBuilder::newPage(const BoxFrame* box, float top)
pageBox->build();
pageBox->layout();

auto pageWidth = std::max(1.f, pageBox->width() - pageBox->marginWidth());
auto pageHeight = std::max(1.f, pageBox->height() - pageBox->marginHeight());
if(auto pageScale = pageStyle->pageScale()) {
pageBox->setPageScale(pageScale.value());
} else {
pageBox->setPageScale(pageWidth / m_document->width());
}

pageBox->setPageTop(std::ceil(top));
pageBox->setPageBottom(std::ceil(top + (pageHeight / pageBox->pageScale())));
pageBox->setPageTop(top);
pageBox->setPageBottom(top + m_document->box()->pageHeight());
m_currentPage = pageBox.get();
m_pages.push_back(std::move(pageBox));
}
Expand Down
9 changes: 7 additions & 2 deletions source/plutobook.cc
Original file line number Diff line number Diff line change
Expand Up @@ -457,9 +457,9 @@ inline const plutobook::Book* toBook(const plutobook_t* book)
return (const plutobook::Book*)(book);
}

plutobook_t* plutobook_create(plutobook_page_size_t size, plutobook_page_margins_t margins, plutobook_media_type_t media)
plutobook_t* plutobook_create(plutobook_page_size_t size, plutobook_page_margins_t margins, plutobook_media_type_t media, float scale)
{
return (plutobook_t*)(new plutobook::Book(size, margins, (plutobook::MediaType)(media)));
return (plutobook_t*)(new plutobook::Book(size, margins, (plutobook::MediaType)(media), scale));
}

void plutobook_destroy(plutobook_t* book)
Expand Down Expand Up @@ -551,6 +551,11 @@ plutobook_page_margins_t plutobook_get_page_margins(const plutobook_t* book)
return toBook(book)->pageMargins();
}

float plutobook_get_page_scale(const plutobook_t* book)
{
return toBook(book)->pageScale();
}

unsigned int plutobook_get_page_count(const plutobook_t* book)
{
return toBook(book)->pageCount();
Expand Down
3 changes: 2 additions & 1 deletion source/plutobook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,11 @@ void PDFCanvas::showPage()
plutobook_pdf_canvas_show_page(m_canvas);
}

Book::Book(const PageSize& size, const PageMargins& margins, MediaType media)
Book::Book(const PageSize& size, const PageMargins& margins, MediaType media, float scale)
: m_pageSize(size)
, m_pageMargins(margins)
, m_mediaType(media)
, m_pageScale(scale)
, m_heap(new Heap(1024 * 32))
{
}
Expand Down

0 comments on commit f6efc11

Please sign in to comment.