X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/03647350fc7cd141953c72e0284e928847d30f44..64ea838d8f4d1853b7d850db93ee565e901d099a:/src/richtext/richtextprint.cpp diff --git a/src/richtext/richtextprint.cpp b/src/richtext/richtextprint.cpp index 2efffa46a5..59c331d02f 100644 --- a/src/richtext/richtextprint.cpp +++ b/src/richtext/richtextprint.cpp @@ -54,6 +54,7 @@ void wxRichTextPrintout::OnPreparePrinting() m_pageBreaksStart.Clear(); m_pageBreaksEnd.Clear(); + m_pageYOffsets.Clear(); int lastStartPos = 0; @@ -66,7 +67,8 @@ void wxRichTextPrintout::OnPreparePrinting() { GetRichTextBuffer()->Invalidate(wxRICHTEXT_ALL); - GetRichTextBuffer()->Layout(*GetDC(), rect, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT); + wxRichTextDrawingContext context(GetRichTextBuffer()); + GetRichTextBuffer()->Layout(*GetDC(), context, rect, rect, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT); // Now calculate the page breaks @@ -80,58 +82,73 @@ void wxRichTextPrintout::OnPreparePrinting() // 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(); + wxRichTextLineList::compatibility_iterator node2 = child->GetLines().GetFirst(); + while (node2) + { + 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 - yOffset; + bool hasHardPageBreak = ((node2 == child->GetLines().GetFirst()) && child->GetAttributes().HasPageBreak()); - 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 - // 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) + { + // Only if we're not at the start of the document, and + // even then, only if either it's a hard break or if the object + // can fit in a whole page (otherwise there's no point in making + // the rest of this page blank). + if (lastLine && (hasHardPageBreak || (line->GetSize().y <= rect.GetHeight()))) + { + // New page starting at this line + int newY = rect.y; - if (((lineY + line->GetSize().y) > rect.GetBottom()) || - ((node2 == child->GetLines().GetFirst()) && child->GetAttributes().HasPageBreak())) - { - // New page starting at this line - int newY = rect.y; + // We increase the offset by the difference between new and old positions - // We increase the offset by the difference between new and old positions + int increaseOffsetBy = lineY - newY; + yOffset += increaseOffsetBy; - int increaseOffsetBy = lineY - newY; - yOffset += increaseOffsetBy; + m_pageBreaksStart.Add(lastStartPos); + m_pageBreaksEnd.Add(lastLine->GetAbsoluteRange().GetEnd()); + m_pageYOffsets.Add(yOffset); - line->SetPosition(wxPoint(line->GetPosition().x, newY - child->GetPosition().y)); + lastStartPos = line->GetAbsoluteRange().GetStart(); + m_numPages ++; + } - if (!lastLine) lastLine = line; - m_pageBreaksStart.Add(lastStartPos); - m_pageBreaksEnd.Add(lastLine->GetAbsoluteRange().GetEnd()); + // 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(); - lastStartPos = line->GetAbsoluteRange().GetStart(); + m_pageBreaksStart.Add(lastStartPos); + m_pageBreaksEnd.Add(lastLine->GetAbsoluteRange().GetEnd()); + m_pageYOffsets.Add(yOffset); - m_numPages ++; - } + m_numPages ++; + } + } - lastLine = line; + lastLine = line; - node2 = node2->GetNext(); + node2 = node2->GetNext(); + } } node = node->GetNext(); } // Closing page break - if (m_pageBreaksStart.GetCount() == 0 || (m_pageBreaksEnd[m_pageBreaksEnd.GetCount()-1] < (GetRichTextBuffer()->GetRange().GetEnd()-1))) - { - m_pageBreaksStart.Add(lastStartPos); - m_pageBreaksEnd.Add(GetRichTextBuffer()->GetRange().GetEnd()); - } + m_pageBreaksStart.Add(lastStartPos); + m_pageBreaksEnd.Add(GetRichTextBuffer()->GetOwnRange().GetEnd()); + m_pageYOffsets.Add(yOffset); } } @@ -181,11 +198,11 @@ void wxRichTextPrintout::RenderPage(wxDC *dc, int page) if (page > 1 || m_headerFooterData.GetShowOnFirstPage()) { - if (m_headerFooterData.GetFont().Ok()) + if (m_headerFooterData.GetFont().IsOk()) dc->SetFont(m_headerFooterData.GetFont()); else dc->SetFont(*wxNORMAL_FONT); - if (m_headerFooterData.GetTextColour().Ok()) + if (m_headerFooterData.GetTextColour().IsOk()) dc->SetTextForeground(m_headerFooterData.GetTextColour()); else dc->SetTextForeground(*wxBLACK); @@ -274,7 +291,26 @@ void wxRichTextPrintout::RenderPage(wxDC *dc, int page) wxRichTextRange rangeToDraw(m_pageBreaksStart[page-1], m_pageBreaksEnd[page-1]); - GetRichTextBuffer()->Draw(*dc, rangeToDraw, wxRichTextRange(-1,-1), textRect, 0 /* descent */, wxRICHTEXT_DRAW_IGNORE_CACHE /* flags */); + wxPoint oldOrigin = dc->GetLogicalOrigin(); + double scaleX, scaleY; + dc->GetUserScale(& scaleX, & scaleY); + + 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)); + + wxRichTextDrawingContext context(GetRichTextBuffer()); + GetRichTextBuffer()->Draw(*dc, context, 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) @@ -312,8 +348,8 @@ 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()) - m_richTextBuffer->SetScale(scale); + // Also, correct the conversions in wxRTC using DC instead of print DC. + m_richTextBuffer->SetScale(scale * float(dc->GetPPI().x)/float(ppiPrinterX)); // Calculate margins int marginLeft = wxRichTextObject::ConvertTenthsMMToPixels(ppiPrinterX, m_marginLeft); @@ -340,7 +376,7 @@ void wxRichTextPrintout::CalculateScaling(wxDC* dc, wxRect& textRect, wxRect& he !m_headerFooterData.GetHeaderText(wxRICHTEXT_PAGE_EVEN, wxRICHTEXT_PAGE_CENTRE).IsEmpty() || !m_headerFooterData.GetHeaderText(wxRICHTEXT_PAGE_EVEN, wxRICHTEXT_PAGE_RIGHT).IsEmpty()) { - if (m_headerFooterData.GetFont().Ok()) + if (m_headerFooterData.GetFont().IsOk()) dc->SetFont(m_headerFooterData.GetFont()); else dc->SetFont(*wxNORMAL_FONT); @@ -365,7 +401,7 @@ void wxRichTextPrintout::CalculateScaling(wxDC* dc, wxRect& textRect, wxRect& he !m_headerFooterData.GetFooterText(wxRICHTEXT_PAGE_EVEN, wxRICHTEXT_PAGE_CENTRE).IsEmpty() || !m_headerFooterData.GetFooterText(wxRICHTEXT_PAGE_EVEN, wxRICHTEXT_PAGE_RIGHT).IsEmpty()) { - if (m_headerFooterData.GetFont().Ok()) + if (m_headerFooterData.GetFont().IsOk()) dc->SetFont(m_headerFooterData.GetFont()); else dc->SetFont(*wxNORMAL_FONT); @@ -444,7 +480,7 @@ void wxRichTextPrinting::SetPrintData(const wxPrintData& printData) (*GetPrintData()) = printData; } -void wxRichTextPrinting::SetPageSetupData(const wxPageSetupData& pageSetupData) +void wxRichTextPrinting::SetPageSetupData(const wxPageSetupDialogData& pageSetupData) { (*GetPageSetupData()) = pageSetupData; } @@ -504,7 +540,7 @@ bool wxRichTextPrinting::PreviewBuffer(const wxRichTextBuffer& buffer) return DoPreview(p1, p2); } -bool wxRichTextPrinting::PrintFile(const wxString& richTextFile) +bool wxRichTextPrinting::PrintFile(const wxString& richTextFile, bool showPrintDialog) { SetRichTextBufferPrinting(new wxRichTextBuffer); @@ -517,19 +553,19 @@ bool wxRichTextPrinting::PrintFile(const wxString& richTextFile) wxRichTextPrintout *p = CreatePrintout(); p->SetRichTextBuffer(m_richTextBufferPrinting); - bool ret = DoPrint(p); + bool ret = DoPrint(p, showPrintDialog); delete p; return ret; } -bool wxRichTextPrinting::PrintBuffer(const wxRichTextBuffer& buffer) +bool wxRichTextPrinting::PrintBuffer(const wxRichTextBuffer& buffer, bool showPrintDialog) { SetRichTextBufferPrinting(new wxRichTextBuffer(buffer)); wxRichTextPrintout *p = CreatePrintout(); p->SetRichTextBuffer(m_richTextBufferPrinting); - bool ret = DoPrint(p); + bool ret = DoPrint(p, showPrintDialog); delete p; return ret; } @@ -539,7 +575,7 @@ bool wxRichTextPrinting::DoPreview(wxRichTextPrintout *printout1, wxRichTextPrin // Pass two printout objects: for preview, and possible printing. wxPrintDialogData printDialogData(*GetPrintData()); wxPrintPreview *preview = new wxPrintPreview(printout1, printout2, &printDialogData); - if (!preview->Ok()) + if (!preview->IsOk()) { delete preview; return false; @@ -554,12 +590,12 @@ bool wxRichTextPrinting::DoPreview(wxRichTextPrintout *printout1, wxRichTextPrin return true; } -bool wxRichTextPrinting::DoPrint(wxRichTextPrintout *printout) +bool wxRichTextPrinting::DoPrint(wxRichTextPrintout *printout, bool showPrintDialog) { wxPrintDialogData printDialogData(*GetPrintData()); wxPrinter printer(&printDialogData); - if (!printer.Print(m_parentWindow, printout, true)) + if (!printer.Print(m_parentWindow, printout, showPrintDialog)) { return false; } @@ -570,7 +606,7 @@ bool wxRichTextPrinting::DoPrint(wxRichTextPrintout *printout) void wxRichTextPrinting::PageSetup() { - if (!GetPrintData()->Ok()) + if (!GetPrintData()->IsOk()) { wxLogError(_("There was a problem during page setup: you may need to set a default printer.")); return;