X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/04ee05f92add0ab92ce08ecb827e3be41336aa06..c81394808bf7efd84e4294e44a9a9a7b7f6dd8a9:/src/richtext/richtextprint.cpp?ds=sidebyside diff --git a/src/richtext/richtextprint.cpp b/src/richtext/richtextprint.cpp index 1082eabbf1..9855d57966 100644 --- a/src/richtext/richtextprint.cpp +++ b/src/richtext/richtextprint.cpp @@ -54,9 +54,10 @@ void wxRichTextPrintout::OnPreparePrinting() m_pageBreaksStart.Clear(); m_pageBreaksEnd.Clear(); - + m_pageYOffsets.Clear(); + int lastStartPos = 0; - + wxRect rect, headerRect, footerRect; /// Sets the DC scaling and returns important page rectangles @@ -67,70 +68,82 @@ void wxRichTextPrintout::OnPreparePrinting() GetRichTextBuffer()->Invalidate(wxRICHTEXT_ALL); GetRichTextBuffer()->Layout(*GetDC(), rect, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT); - + // Now calculate the page breaks - + int yOffset = 0; - + wxRichTextLine* lastLine = NULL; - + wxRichTextObjectList::compatibility_iterator node = GetRichTextBuffer()->GetChildren().GetFirst(); while (node) { // child is a paragraph wxRichTextParagraph* child = wxDynamicCast(node->GetData(), wxRichTextParagraph); wxASSERT (child != NULL); - - wxRichTextLineList::compatibility_iterator node2 = child->GetLines().GetFirst(); - while (node2) + if (child) { - wxRichTextLine* line = node2->GetData(); - - // Set the line to the page-adjusted position - line->SetPosition(wxPoint(line->GetPosition().x, line->GetPosition().y - yOffset)); - - int lineY = child->GetPosition().y + line->GetPosition().y; - - // Break the page if either we're going off the bottom, or this paragraph specifies - // an explicit page break - - if (((lineY + line->GetSize().y) > rect.GetBottom()) || - ((node2 == child->GetLines().GetFirst()) && child->GetAttributes().HasPageBreak())) + wxRichTextLineList::compatibility_iterator node2 = child->GetLines().GetFirst(); + while (node2) { - // New page starting at this line - int newY = rect.y; - - // We increase the offset by the difference between new and old positions - - int increaseOffsetBy = lineY - newY; - yOffset += increaseOffsetBy; - - line->SetPosition(wxPoint(line->GetPosition().x, newY - child->GetPosition().y)); - - if (!lastLine) + wxRichTextLine* line = node2->GetData(); + + int lineY = child->GetPosition().y + line->GetPosition().y - yOffset; + bool hasHardPageBreak = ((node2 == child->GetLines().GetFirst()) && child->GetAttributes().HasPageBreak()); + + // Break the page if either we're going off the bottom, or this paragraph specifies + // an explicit page break + + if (((lineY + line->GetSize().y) > rect.GetBottom()) || hasHardPageBreak) + { + // New page starting at this line + int newY = rect.y; + + // We increase the offset by the difference between new and old positions + + int increaseOffsetBy = lineY - newY; + yOffset += increaseOffsetBy; + + if (!lastLine) + lastLine = line; + + m_pageBreaksStart.Add(lastStartPos); + m_pageBreaksEnd.Add(lastLine->GetAbsoluteRange().GetEnd()); + m_pageYOffsets.Add(yOffset); + + lastStartPos = line->GetAbsoluteRange().GetStart(); lastLine = line; - - m_pageBreaksStart.Add(lastStartPos); - m_pageBreaksEnd.Add(lastLine->GetAbsoluteRange().GetEnd()); - - lastStartPos = line->GetAbsoluteRange().GetStart(); - - m_numPages ++; - } - - lastLine = line; - node2 = node2->GetNext(); + m_numPages ++; + + // Now create page breaks for the rest of the line, if it's larger than the page height + int contentLeft = line->GetSize().y - rect.GetHeight(); + while (contentLeft >= 0) + { + yOffset += rect.GetHeight(); + contentLeft -= rect.GetHeight(); + + m_pageBreaksStart.Add(lastStartPos); + m_pageBreaksEnd.Add(lastLine->GetAbsoluteRange().GetEnd()); + m_pageYOffsets.Add(yOffset); + } + } + + lastLine = line; + + node2 = node2->GetNext(); + } } node = node->GetNext(); } // Closing page break - if (m_pageBreaksStart.GetCount() == 0 || (m_pageBreaksEnd[m_pageBreaksEnd.GetCount()-1] < (GetRichTextBuffer()->GetRange().GetEnd()-1))) + if (m_pageBreaksStart.GetCount() == 0 || (m_pageBreaksEnd[m_pageBreaksEnd.GetCount()-1] < (GetRichTextBuffer()->GetOwnRange().GetEnd()-1))) { m_pageBreaksStart.Add(lastStartPos); - m_pageBreaksEnd.Add(GetRichTextBuffer()->GetRange().GetEnd()); + m_pageBreaksEnd.Add(GetRichTextBuffer()->GetOwnRange().GetEnd()); + m_pageYOffsets.Add(yOffset); } } } @@ -173,7 +186,7 @@ void wxRichTextPrintout::RenderPage(wxDC *dc, int page) return; wxBusyCursor wait; - + wxRect textRect, headerRect, footerRect; /// Sets the DC scaling and returns important page rectangles @@ -191,7 +204,7 @@ void wxRichTextPrintout::RenderPage(wxDC *dc, int page) dc->SetTextForeground(*wxBLACK); dc->SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT); - // Draw header, if any + // Draw header, if any wxRichTextOddEvenPage oddEven = ((page % 2) == 1) ? wxRICHTEXT_PAGE_ODD : wxRICHTEXT_PAGE_EVEN; wxString headerTextCentre = m_headerFooterData.GetHeaderText(oddEven, wxRICHTEXT_PAGE_CENTRE); @@ -204,7 +217,7 @@ void wxRichTextPrintout::RenderPage(wxDC *dc, int page) //int tx, ty; //dc->GetTextExtent(headerTextLeft, & tx, & ty); - + int x = headerRect.GetLeft(); int y = headerRect.GetX(); dc->DrawText(headerTextLeft, x, y); @@ -232,7 +245,7 @@ void wxRichTextPrintout::RenderPage(wxDC *dc, int page) dc->DrawText(headerTextRight, x, y); } - // Draw footer, if any + // Draw footer, if any wxString footerTextCentre = m_headerFooterData.GetFooterText(oddEven, wxRICHTEXT_PAGE_CENTRE); wxString footerTextLeft = m_headerFooterData.GetFooterText(oddEven, wxRICHTEXT_PAGE_LEFT); wxString footerTextRight = m_headerFooterData.GetFooterText(oddEven, wxRICHTEXT_PAGE_RIGHT); @@ -270,11 +283,29 @@ void wxRichTextPrintout::RenderPage(wxDC *dc, int page) int y = footerRect.GetBottom() - ty; dc->DrawText(footerTextRight, x, y); } - } + } wxRichTextRange rangeToDraw(m_pageBreaksStart[page-1], m_pageBreaksEnd[page-1]); + + wxPoint oldOrigin = dc->GetLogicalOrigin(); + double scaleX, scaleY; + dc->GetUserScale(& scaleX, & scaleY); - GetRichTextBuffer()->Draw(*dc, rangeToDraw, wxRichTextRange(-1,-1), textRect, 0 /* descent */, wxRICHTEXT_DRAW_IGNORE_CACHE /* flags */); + int yOffset = 0; + if (page > 1) + yOffset = m_pageYOffsets[page-2]; + + if (yOffset != oldOrigin.y) + dc->SetLogicalOrigin(oldOrigin.x, oldOrigin.y + yOffset); + + dc->SetClippingRegion(wxRect(textRect.x, textRect.y + yOffset, textRect.width, textRect.height)); + + GetRichTextBuffer()->Draw(*dc, rangeToDraw, wxRichTextSelection(), textRect, 0 /* descent */, wxRICHTEXT_DRAW_IGNORE_CACHE|wxRICHTEXT_DRAW_PRINT /* flags */); + + dc->DestroyClippingRegion(); + + if (yOffset != oldOrigin.y) + dc->SetLogicalOrigin(oldOrigin.x, oldOrigin.y); } void wxRichTextPrintout::SetMargins(int top, int bottom, int left, int right) @@ -304,7 +335,7 @@ void wxRichTextPrintout::CalculateScaling(wxDC* dc, wxRect& textRect, wxRect& he int w, h; dc->GetSize(&w, &h); GetPageSizePixels(&pageWidth, &pageHeight); - + // If printer pageWidth == current DC width, then this doesn't // change. But w might be the preview bitmap width, so scale down. float previewScale = (float)(w/(float)pageWidth); @@ -312,24 +343,24 @@ void wxRichTextPrintout::CalculateScaling(wxDC* dc, wxRect& textRect, wxRect& he // The dimensions used for indentation etc. have to be unscaled // during printing to be correct when scaling is applied. - if (!IsPreview()) + // if (!IsPreview()) m_richTextBuffer->SetScale(scale); - + // Calculate margins int marginLeft = wxRichTextObject::ConvertTenthsMMToPixels(ppiPrinterX, m_marginLeft); int marginTop = wxRichTextObject::ConvertTenthsMMToPixels(ppiPrinterX, m_marginTop); int marginRight = wxRichTextObject::ConvertTenthsMMToPixels(ppiPrinterX, m_marginRight); int marginBottom = wxRichTextObject::ConvertTenthsMMToPixels(ppiPrinterX, m_marginBottom); - + // Header and footer margins int headerMargin = wxRichTextObject::ConvertTenthsMMToPixels(ppiPrinterX, m_headerFooterData.GetHeaderMargin()); int footerMargin = wxRichTextObject::ConvertTenthsMMToPixels(ppiPrinterX, m_headerFooterData.GetFooterMargin()); - + dc->SetUserScale(overallScale, overallScale); wxRect rect((int) (marginLeft/scale), (int) (marginTop/scale), (int) ((pageWidth - marginLeft - marginRight)/scale), (int)((pageHeight - marginTop - marginBottom)/scale)); - + headerRect = wxRect(0, 0, 0, 0); if (!m_headerFooterData.GetHeaderText(wxRICHTEXT_PAGE_ODD, wxRICHTEXT_PAGE_LEFT).IsEmpty() || @@ -344,15 +375,15 @@ void wxRichTextPrintout::CalculateScaling(wxDC* dc, wxRect& textRect, wxRect& he dc->SetFont(m_headerFooterData.GetFont()); else dc->SetFont(*wxNORMAL_FONT); - + int charHeight = dc->GetCharHeight(); - + int headerHeight = (int) (charHeight + headerMargin/scale); headerRect = wxRect(rect.x, rect.y, rect.width, headerHeight); rect.y += headerHeight; - rect.height -= headerHeight; + rect.height -= headerHeight; } footerRect = wxRect(0, 0, 0, 0); @@ -369,14 +400,14 @@ void wxRichTextPrintout::CalculateScaling(wxDC* dc, wxRect& textRect, wxRect& he dc->SetFont(m_headerFooterData.GetFont()); else dc->SetFont(*wxNORMAL_FONT); - + int charHeight = dc->GetCharHeight(); - + int footerHeight = (int) (charHeight + footerMargin/scale); footerRect = wxRect(rect.x, rect.y + rect.height, rect.width, footerHeight); - rect.height -= footerHeight; + rect.height -= footerHeight; } textRect = rect; @@ -414,7 +445,7 @@ wxRichTextPrinting::wxRichTextPrinting(const wxString& name, wxWindow *parentWin m_parentWindow = parentWindow; m_title = name; m_printData = NULL; - + m_previewRect = wxRect(wxPoint(100, 100), wxSize(800, 800)); m_pageSetupData = new wxPageSetupDialogData; @@ -481,7 +512,7 @@ bool wxRichTextPrinting::PreviewFile(const wxString& richTextFile) } else SetRichTextBufferPrinting(new wxRichTextBuffer(*m_richTextBufferPreview)); - + wxRichTextPrintout *p1 = CreatePrintout(); p1->SetRichTextBuffer(m_richTextBufferPreview); @@ -497,7 +528,7 @@ bool wxRichTextPrinting::PreviewBuffer(const wxRichTextBuffer& buffer) wxRichTextPrintout *p1 = CreatePrintout(); p1->SetRichTextBuffer(m_richTextBufferPreview); - + wxRichTextPrintout *p2 = CreatePrintout(); p2->SetRichTextBuffer(m_richTextBufferPrinting);