Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #include "nsSimplePageSequenceFrame.h" |
michael@0 | 7 | |
michael@0 | 8 | #include "nsCOMPtr.h" |
michael@0 | 9 | #include "nsPresContext.h" |
michael@0 | 10 | #include "gfxContext.h" |
michael@0 | 11 | #include "nsRenderingContext.h" |
michael@0 | 12 | #include "nsGkAtoms.h" |
michael@0 | 13 | #include "nsIPresShell.h" |
michael@0 | 14 | #include "nsIPrintSettings.h" |
michael@0 | 15 | #include "nsPageFrame.h" |
michael@0 | 16 | #include "nsSubDocumentFrame.h" |
michael@0 | 17 | #include "nsRegion.h" |
michael@0 | 18 | #include "nsCSSFrameConstructor.h" |
michael@0 | 19 | #include "nsContentUtils.h" |
michael@0 | 20 | #include "nsDisplayList.h" |
michael@0 | 21 | #include "nsHTMLCanvasFrame.h" |
michael@0 | 22 | #include "mozilla/dom/HTMLCanvasElement.h" |
michael@0 | 23 | #include "nsICanvasRenderingContextInternal.h" |
michael@0 | 24 | #include "nsIDateTimeFormat.h" |
michael@0 | 25 | #include "nsServiceManagerUtils.h" |
michael@0 | 26 | #include <algorithm> |
michael@0 | 27 | |
michael@0 | 28 | // DateTime Includes |
michael@0 | 29 | #include "nsDateTimeFormatCID.h" |
michael@0 | 30 | |
michael@0 | 31 | #define OFFSET_NOT_SET -1 |
michael@0 | 32 | |
michael@0 | 33 | // Print Options |
michael@0 | 34 | #include "nsIPrintOptions.h" |
michael@0 | 35 | |
michael@0 | 36 | using namespace mozilla; |
michael@0 | 37 | using namespace mozilla::dom; |
michael@0 | 38 | |
michael@0 | 39 | static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printsettings-service;1"; |
michael@0 | 40 | |
michael@0 | 41 | // |
michael@0 | 42 | |
michael@0 | 43 | #include "prlog.h" |
michael@0 | 44 | #ifdef PR_LOGGING |
michael@0 | 45 | PRLogModuleInfo * |
michael@0 | 46 | GetLayoutPrintingLog() |
michael@0 | 47 | { |
michael@0 | 48 | static PRLogModuleInfo *sLog; |
michael@0 | 49 | if (!sLog) |
michael@0 | 50 | sLog = PR_NewLogModule("printing-layout"); |
michael@0 | 51 | return sLog; |
michael@0 | 52 | } |
michael@0 | 53 | #define PR_PL(_p1) PR_LOG(GetLayoutPrintingLog(), PR_LOG_DEBUG, _p1) |
michael@0 | 54 | #else |
michael@0 | 55 | #define PR_PL(_p1) |
michael@0 | 56 | #endif |
michael@0 | 57 | |
michael@0 | 58 | nsIFrame* |
michael@0 | 59 | NS_NewSimplePageSequenceFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) |
michael@0 | 60 | { |
michael@0 | 61 | return new (aPresShell) nsSimplePageSequenceFrame(aContext); |
michael@0 | 62 | } |
michael@0 | 63 | |
michael@0 | 64 | NS_IMPL_FRAMEARENA_HELPERS(nsSimplePageSequenceFrame) |
michael@0 | 65 | |
michael@0 | 66 | nsSimplePageSequenceFrame::nsSimplePageSequenceFrame(nsStyleContext* aContext) : |
michael@0 | 67 | nsContainerFrame(aContext), |
michael@0 | 68 | mTotalPages(-1), |
michael@0 | 69 | mSelectionHeight(-1), |
michael@0 | 70 | mYSelOffset(0), |
michael@0 | 71 | mCalledBeginPage(false), |
michael@0 | 72 | mCurrentCanvasListSetup(false) |
michael@0 | 73 | { |
michael@0 | 74 | nscoord halfInch = PresContext()->CSSTwipsToAppUnits(NS_INCHES_TO_TWIPS(0.5)); |
michael@0 | 75 | mMargin.SizeTo(halfInch, halfInch, halfInch, halfInch); |
michael@0 | 76 | |
michael@0 | 77 | // XXX Unsafe to assume successful allocation |
michael@0 | 78 | mPageData = new nsSharedPageData(); |
michael@0 | 79 | mPageData->mHeadFootFont = |
michael@0 | 80 | *PresContext()->GetDefaultFont(kGenericFont_serif, |
michael@0 | 81 | aContext->StyleFont()->mLanguage); |
michael@0 | 82 | mPageData->mHeadFootFont.size = nsPresContext::CSSPointsToAppUnits(10); |
michael@0 | 83 | |
michael@0 | 84 | nsresult rv; |
michael@0 | 85 | mPageData->mPrintOptions = do_GetService(sPrintOptionsContractID, &rv); |
michael@0 | 86 | |
michael@0 | 87 | // Doing this here so we only have to go get these formats once |
michael@0 | 88 | SetPageNumberFormat("pagenumber", "%1$d", true); |
michael@0 | 89 | SetPageNumberFormat("pageofpages", "%1$d of %2$d", false); |
michael@0 | 90 | } |
michael@0 | 91 | |
michael@0 | 92 | nsSimplePageSequenceFrame::~nsSimplePageSequenceFrame() |
michael@0 | 93 | { |
michael@0 | 94 | delete mPageData; |
michael@0 | 95 | ResetPrintCanvasList(); |
michael@0 | 96 | } |
michael@0 | 97 | |
michael@0 | 98 | NS_QUERYFRAME_HEAD(nsSimplePageSequenceFrame) |
michael@0 | 99 | NS_QUERYFRAME_ENTRY(nsIPageSequenceFrame) |
michael@0 | 100 | NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame) |
michael@0 | 101 | |
michael@0 | 102 | //---------------------------------------------------------------------- |
michael@0 | 103 | |
michael@0 | 104 | void |
michael@0 | 105 | nsSimplePageSequenceFrame::SetDesiredSize(nsHTMLReflowMetrics& aDesiredSize, |
michael@0 | 106 | const nsHTMLReflowState& aReflowState, |
michael@0 | 107 | nscoord aWidth, |
michael@0 | 108 | nscoord aHeight) |
michael@0 | 109 | { |
michael@0 | 110 | // Aim to fill the whole size of the document, not only so we |
michael@0 | 111 | // can act as a background in print preview but also handle overflow |
michael@0 | 112 | // in child page frames correctly. |
michael@0 | 113 | // Use availableWidth so we don't cause a needless horizontal scrollbar. |
michael@0 | 114 | aDesiredSize.Width() = std::max(aReflowState.AvailableWidth(), |
michael@0 | 115 | nscoord(aWidth * PresContext()->GetPrintPreviewScale())); |
michael@0 | 116 | aDesiredSize.Height() = std::max(aReflowState.ComputedHeight(), |
michael@0 | 117 | nscoord(aHeight * PresContext()->GetPrintPreviewScale())); |
michael@0 | 118 | } |
michael@0 | 119 | |
michael@0 | 120 | nsresult |
michael@0 | 121 | nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext, |
michael@0 | 122 | nsHTMLReflowMetrics& aDesiredSize, |
michael@0 | 123 | const nsHTMLReflowState& aReflowState, |
michael@0 | 124 | nsReflowStatus& aStatus) |
michael@0 | 125 | { |
michael@0 | 126 | NS_PRECONDITION(aPresContext->IsRootPaginatedDocument(), |
michael@0 | 127 | "A Page Sequence is only for real pages"); |
michael@0 | 128 | DO_GLOBAL_REFLOW_COUNT("nsSimplePageSequenceFrame"); |
michael@0 | 129 | DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); |
michael@0 | 130 | NS_FRAME_TRACE_REFLOW_IN("nsSimplePageSequenceFrame::Reflow"); |
michael@0 | 131 | |
michael@0 | 132 | aStatus = NS_FRAME_COMPLETE; // we're always complete |
michael@0 | 133 | |
michael@0 | 134 | // Don't do incremental reflow until we've taught tables how to do |
michael@0 | 135 | // it right in paginated mode. |
michael@0 | 136 | if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) { |
michael@0 | 137 | // Return our desired size |
michael@0 | 138 | SetDesiredSize(aDesiredSize, aReflowState, mSize.width, mSize.height); |
michael@0 | 139 | aDesiredSize.SetOverflowAreasToDesiredBounds(); |
michael@0 | 140 | FinishAndStoreOverflow(&aDesiredSize); |
michael@0 | 141 | return NS_OK; |
michael@0 | 142 | } |
michael@0 | 143 | |
michael@0 | 144 | // See if we can get a Print Settings from the Context |
michael@0 | 145 | if (!mPageData->mPrintSettings && |
michael@0 | 146 | aPresContext->Medium() == nsGkAtoms::print) { |
michael@0 | 147 | mPageData->mPrintSettings = aPresContext->GetPrintSettings(); |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | // now get out margins & edges |
michael@0 | 151 | if (mPageData->mPrintSettings) { |
michael@0 | 152 | nsIntMargin unwriteableTwips; |
michael@0 | 153 | mPageData->mPrintSettings->GetUnwriteableMarginInTwips(unwriteableTwips); |
michael@0 | 154 | NS_ASSERTION(unwriteableTwips.left >= 0 && unwriteableTwips.top >= 0 && |
michael@0 | 155 | unwriteableTwips.right >= 0 && unwriteableTwips.bottom >= 0, |
michael@0 | 156 | "Unwriteable twips should be non-negative"); |
michael@0 | 157 | |
michael@0 | 158 | nsIntMargin marginTwips; |
michael@0 | 159 | mPageData->mPrintSettings->GetMarginInTwips(marginTwips); |
michael@0 | 160 | mMargin = aPresContext->CSSTwipsToAppUnits(marginTwips + unwriteableTwips); |
michael@0 | 161 | |
michael@0 | 162 | int16_t printType; |
michael@0 | 163 | mPageData->mPrintSettings->GetPrintRange(&printType); |
michael@0 | 164 | mPrintRangeType = printType; |
michael@0 | 165 | |
michael@0 | 166 | nsIntMargin edgeTwips; |
michael@0 | 167 | mPageData->mPrintSettings->GetEdgeInTwips(edgeTwips); |
michael@0 | 168 | |
michael@0 | 169 | // sanity check the values. three inches are sometimes needed |
michael@0 | 170 | int32_t inchInTwips = NS_INCHES_TO_INT_TWIPS(3.0); |
michael@0 | 171 | edgeTwips.top = clamped(edgeTwips.top, 0, inchInTwips); |
michael@0 | 172 | edgeTwips.bottom = clamped(edgeTwips.bottom, 0, inchInTwips); |
michael@0 | 173 | edgeTwips.left = clamped(edgeTwips.left, 0, inchInTwips); |
michael@0 | 174 | edgeTwips.right = clamped(edgeTwips.right, 0, inchInTwips); |
michael@0 | 175 | |
michael@0 | 176 | mPageData->mEdgePaperMargin = |
michael@0 | 177 | aPresContext->CSSTwipsToAppUnits(edgeTwips + unwriteableTwips); |
michael@0 | 178 | } |
michael@0 | 179 | |
michael@0 | 180 | // *** Special Override *** |
michael@0 | 181 | // If this is a sub-sdoc (meaning it doesn't take the whole page) |
michael@0 | 182 | // and if this Document is in the upper left hand corner |
michael@0 | 183 | // we need to suppress the top margin or it will reflow too small |
michael@0 | 184 | |
michael@0 | 185 | nsSize pageSize = aPresContext->GetPageSize(); |
michael@0 | 186 | |
michael@0 | 187 | mPageData->mReflowSize = pageSize; |
michael@0 | 188 | // If we're printing a selection, we need to reflow with |
michael@0 | 189 | // unconstrained height, to make sure we'll get to the selection |
michael@0 | 190 | // even if it's beyond the first page of content. |
michael@0 | 191 | if (nsIPrintSettings::kRangeSelection == mPrintRangeType) { |
michael@0 | 192 | mPageData->mReflowSize.height = NS_UNCONSTRAINEDSIZE; |
michael@0 | 193 | } |
michael@0 | 194 | mPageData->mReflowMargin = mMargin; |
michael@0 | 195 | |
michael@0 | 196 | // We use the CSS "margin" property on the -moz-page pseudoelement |
michael@0 | 197 | // to determine the space between each page in print preview. |
michael@0 | 198 | // Keep a running y-offset for each page. |
michael@0 | 199 | nscoord y = 0; |
michael@0 | 200 | nscoord maxXMost = 0; |
michael@0 | 201 | |
michael@0 | 202 | // Tile the pages vertically |
michael@0 | 203 | nsHTMLReflowMetrics kidSize(aReflowState); |
michael@0 | 204 | for (nsIFrame* kidFrame = mFrames.FirstChild(); nullptr != kidFrame; ) { |
michael@0 | 205 | // Set the shared data into the page frame before reflow |
michael@0 | 206 | nsPageFrame * pf = static_cast<nsPageFrame*>(kidFrame); |
michael@0 | 207 | pf->SetSharedPageData(mPageData); |
michael@0 | 208 | |
michael@0 | 209 | // Reflow the page |
michael@0 | 210 | nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, |
michael@0 | 211 | pageSize); |
michael@0 | 212 | nsReflowStatus status; |
michael@0 | 213 | |
michael@0 | 214 | kidReflowState.SetComputedWidth(kidReflowState.AvailableWidth()); |
michael@0 | 215 | //kidReflowState.SetComputedHeight(kidReflowState.AvailableHeight()); |
michael@0 | 216 | PR_PL(("AV W: %d H: %d\n", kidReflowState.AvailableWidth(), kidReflowState.AvailableHeight())); |
michael@0 | 217 | |
michael@0 | 218 | nsMargin pageCSSMargin = kidReflowState.ComputedPhysicalMargin(); |
michael@0 | 219 | y += pageCSSMargin.top; |
michael@0 | 220 | const nscoord x = pageCSSMargin.left; |
michael@0 | 221 | |
michael@0 | 222 | // Place and size the page. If the page is narrower than our |
michael@0 | 223 | // max width then center it horizontally |
michael@0 | 224 | ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, x, y, 0, status); |
michael@0 | 225 | |
michael@0 | 226 | FinishReflowChild(kidFrame, aPresContext, kidSize, nullptr, x, y, 0); |
michael@0 | 227 | y += kidSize.Height(); |
michael@0 | 228 | y += pageCSSMargin.bottom; |
michael@0 | 229 | |
michael@0 | 230 | maxXMost = std::max(maxXMost, x + kidSize.Width() + pageCSSMargin.right); |
michael@0 | 231 | |
michael@0 | 232 | // Is the page complete? |
michael@0 | 233 | nsIFrame* kidNextInFlow = kidFrame->GetNextInFlow(); |
michael@0 | 234 | |
michael@0 | 235 | if (NS_FRAME_IS_FULLY_COMPLETE(status)) { |
michael@0 | 236 | NS_ASSERTION(!kidNextInFlow, "bad child flow list"); |
michael@0 | 237 | } else if (!kidNextInFlow) { |
michael@0 | 238 | // The page isn't complete and it doesn't have a next-in-flow, so |
michael@0 | 239 | // create a continuing page. |
michael@0 | 240 | nsIFrame* continuingPage = aPresContext->PresShell()->FrameConstructor()-> |
michael@0 | 241 | CreateContinuingFrame(aPresContext, kidFrame, this); |
michael@0 | 242 | |
michael@0 | 243 | // Add it to our child list |
michael@0 | 244 | mFrames.InsertFrame(nullptr, kidFrame, continuingPage); |
michael@0 | 245 | } |
michael@0 | 246 | |
michael@0 | 247 | // Get the next page |
michael@0 | 248 | kidFrame = kidFrame->GetNextSibling(); |
michael@0 | 249 | } |
michael@0 | 250 | |
michael@0 | 251 | // Get Total Page Count |
michael@0 | 252 | nsIFrame* page; |
michael@0 | 253 | int32_t pageTot = 0; |
michael@0 | 254 | for (page = mFrames.FirstChild(); page; page = page->GetNextSibling()) { |
michael@0 | 255 | pageTot++; |
michael@0 | 256 | } |
michael@0 | 257 | |
michael@0 | 258 | // Set Page Number Info |
michael@0 | 259 | int32_t pageNum = 1; |
michael@0 | 260 | for (page = mFrames.FirstChild(); page; page = page->GetNextSibling()) { |
michael@0 | 261 | nsPageFrame * pf = static_cast<nsPageFrame*>(page); |
michael@0 | 262 | if (pf != nullptr) { |
michael@0 | 263 | pf->SetPageNumInfo(pageNum, pageTot); |
michael@0 | 264 | } |
michael@0 | 265 | pageNum++; |
michael@0 | 266 | } |
michael@0 | 267 | |
michael@0 | 268 | // Create current Date/Time String |
michael@0 | 269 | if (!mDateFormatter) |
michael@0 | 270 | mDateFormatter = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID); |
michael@0 | 271 | |
michael@0 | 272 | NS_ENSURE_TRUE(mDateFormatter, NS_ERROR_FAILURE); |
michael@0 | 273 | |
michael@0 | 274 | nsAutoString formattedDateString; |
michael@0 | 275 | time_t ltime; |
michael@0 | 276 | time( <ime ); |
michael@0 | 277 | if (NS_SUCCEEDED(mDateFormatter->FormatTime(nullptr /* nsILocale* locale */, |
michael@0 | 278 | kDateFormatShort, |
michael@0 | 279 | kTimeFormatNoSeconds, |
michael@0 | 280 | ltime, |
michael@0 | 281 | formattedDateString))) { |
michael@0 | 282 | SetDateTimeStr(formattedDateString); |
michael@0 | 283 | } |
michael@0 | 284 | |
michael@0 | 285 | // Return our desired size |
michael@0 | 286 | // Adjust the reflow size by PrintPreviewScale so the scrollbars end up the |
michael@0 | 287 | // correct size |
michael@0 | 288 | SetDesiredSize(aDesiredSize, aReflowState, maxXMost, y); |
michael@0 | 289 | |
michael@0 | 290 | aDesiredSize.SetOverflowAreasToDesiredBounds(); |
michael@0 | 291 | FinishAndStoreOverflow(&aDesiredSize); |
michael@0 | 292 | |
michael@0 | 293 | // cache the size so we can set the desired size |
michael@0 | 294 | // for the other reflows that happen |
michael@0 | 295 | mSize.width = maxXMost; |
michael@0 | 296 | mSize.height = y; |
michael@0 | 297 | |
michael@0 | 298 | NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus); |
michael@0 | 299 | NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); |
michael@0 | 300 | return NS_OK; |
michael@0 | 301 | } |
michael@0 | 302 | |
michael@0 | 303 | //---------------------------------------------------------------------- |
michael@0 | 304 | |
michael@0 | 305 | #ifdef DEBUG_FRAME_DUMP |
michael@0 | 306 | nsresult |
michael@0 | 307 | nsSimplePageSequenceFrame::GetFrameName(nsAString& aResult) const |
michael@0 | 308 | { |
michael@0 | 309 | return MakeFrameName(NS_LITERAL_STRING("SimplePageSequence"), aResult); |
michael@0 | 310 | } |
michael@0 | 311 | #endif |
michael@0 | 312 | |
michael@0 | 313 | //==================================================================== |
michael@0 | 314 | //== Asynch Printing |
michael@0 | 315 | //==================================================================== |
michael@0 | 316 | NS_IMETHODIMP |
michael@0 | 317 | nsSimplePageSequenceFrame::GetCurrentPageNum(int32_t* aPageNum) |
michael@0 | 318 | { |
michael@0 | 319 | NS_ENSURE_ARG_POINTER(aPageNum); |
michael@0 | 320 | |
michael@0 | 321 | *aPageNum = mPageNum; |
michael@0 | 322 | return NS_OK; |
michael@0 | 323 | } |
michael@0 | 324 | |
michael@0 | 325 | NS_IMETHODIMP |
michael@0 | 326 | nsSimplePageSequenceFrame::GetNumPages(int32_t* aNumPages) |
michael@0 | 327 | { |
michael@0 | 328 | NS_ENSURE_ARG_POINTER(aNumPages); |
michael@0 | 329 | |
michael@0 | 330 | *aNumPages = mTotalPages; |
michael@0 | 331 | return NS_OK; |
michael@0 | 332 | } |
michael@0 | 333 | |
michael@0 | 334 | NS_IMETHODIMP |
michael@0 | 335 | nsSimplePageSequenceFrame::IsDoingPrintRange(bool* aDoing) |
michael@0 | 336 | { |
michael@0 | 337 | NS_ENSURE_ARG_POINTER(aDoing); |
michael@0 | 338 | |
michael@0 | 339 | *aDoing = mDoingPageRange; |
michael@0 | 340 | return NS_OK; |
michael@0 | 341 | } |
michael@0 | 342 | |
michael@0 | 343 | NS_IMETHODIMP |
michael@0 | 344 | nsSimplePageSequenceFrame::GetPrintRange(int32_t* aFromPage, int32_t* aToPage) |
michael@0 | 345 | { |
michael@0 | 346 | NS_ENSURE_ARG_POINTER(aFromPage); |
michael@0 | 347 | NS_ENSURE_ARG_POINTER(aToPage); |
michael@0 | 348 | |
michael@0 | 349 | *aFromPage = mFromPageNum; |
michael@0 | 350 | *aToPage = mToPageNum; |
michael@0 | 351 | return NS_OK; |
michael@0 | 352 | } |
michael@0 | 353 | |
michael@0 | 354 | // Helper Function |
michael@0 | 355 | void |
michael@0 | 356 | nsSimplePageSequenceFrame::SetPageNumberFormat(const char* aPropName, const char* aDefPropVal, bool aPageNumOnly) |
michael@0 | 357 | { |
michael@0 | 358 | // Doing this here so we only have to go get these formats once |
michael@0 | 359 | nsXPIDLString pageNumberFormat; |
michael@0 | 360 | // Now go get the Localized Page Formating String |
michael@0 | 361 | nsresult rv = |
michael@0 | 362 | nsContentUtils::GetLocalizedString(nsContentUtils::ePRINTING_PROPERTIES, |
michael@0 | 363 | aPropName, pageNumberFormat); |
michael@0 | 364 | if (NS_FAILED(rv)) { // back stop formatting |
michael@0 | 365 | pageNumberFormat.AssignASCII(aDefPropVal); |
michael@0 | 366 | } |
michael@0 | 367 | |
michael@0 | 368 | SetPageNumberFormat(pageNumberFormat, aPageNumOnly); |
michael@0 | 369 | } |
michael@0 | 370 | |
michael@0 | 371 | NS_IMETHODIMP |
michael@0 | 372 | nsSimplePageSequenceFrame::StartPrint(nsPresContext* aPresContext, |
michael@0 | 373 | nsIPrintSettings* aPrintSettings, |
michael@0 | 374 | const nsAString& aDocTitle, |
michael@0 | 375 | const nsAString& aDocURL) |
michael@0 | 376 | { |
michael@0 | 377 | NS_ENSURE_ARG_POINTER(aPresContext); |
michael@0 | 378 | NS_ENSURE_ARG_POINTER(aPrintSettings); |
michael@0 | 379 | |
michael@0 | 380 | if (!mPageData->mPrintSettings) { |
michael@0 | 381 | mPageData->mPrintSettings = aPrintSettings; |
michael@0 | 382 | } |
michael@0 | 383 | |
michael@0 | 384 | if (!aDocTitle.IsEmpty()) { |
michael@0 | 385 | mPageData->mDocTitle = aDocTitle; |
michael@0 | 386 | } |
michael@0 | 387 | if (!aDocURL.IsEmpty()) { |
michael@0 | 388 | mPageData->mDocURL = aDocURL; |
michael@0 | 389 | } |
michael@0 | 390 | |
michael@0 | 391 | aPrintSettings->GetStartPageRange(&mFromPageNum); |
michael@0 | 392 | aPrintSettings->GetEndPageRange(&mToPageNum); |
michael@0 | 393 | aPrintSettings->GetPageRanges(mPageRanges); |
michael@0 | 394 | |
michael@0 | 395 | mDoingPageRange = nsIPrintSettings::kRangeSpecifiedPageRange == mPrintRangeType || |
michael@0 | 396 | nsIPrintSettings::kRangeSelection == mPrintRangeType; |
michael@0 | 397 | |
michael@0 | 398 | // If printing a range of pages make sure at least the starting page |
michael@0 | 399 | // number is valid |
michael@0 | 400 | int32_t totalPages = mFrames.GetLength(); |
michael@0 | 401 | |
michael@0 | 402 | if (mDoingPageRange) { |
michael@0 | 403 | if (mFromPageNum > totalPages) { |
michael@0 | 404 | return NS_ERROR_INVALID_ARG; |
michael@0 | 405 | } |
michael@0 | 406 | } |
michael@0 | 407 | |
michael@0 | 408 | // Begin printing of the document |
michael@0 | 409 | nsresult rv = NS_OK; |
michael@0 | 410 | |
michael@0 | 411 | // Determine if we are rendering only the selection |
michael@0 | 412 | aPresContext->SetIsRenderingOnlySelection(nsIPrintSettings::kRangeSelection == mPrintRangeType); |
michael@0 | 413 | |
michael@0 | 414 | |
michael@0 | 415 | if (mDoingPageRange) { |
michael@0 | 416 | // XXX because of the hack for making the selection all print on one page |
michael@0 | 417 | // we must make sure that the page is sized correctly before printing. |
michael@0 | 418 | nscoord height = aPresContext->GetPageSize().height; |
michael@0 | 419 | |
michael@0 | 420 | int32_t pageNum = 1; |
michael@0 | 421 | nscoord y = 0;//mMargin.top; |
michael@0 | 422 | |
michael@0 | 423 | for (nsIFrame* page = mFrames.FirstChild(); page; |
michael@0 | 424 | page = page->GetNextSibling()) { |
michael@0 | 425 | if (pageNum >= mFromPageNum && pageNum <= mToPageNum) { |
michael@0 | 426 | nsRect rect = page->GetRect(); |
michael@0 | 427 | rect.y = y; |
michael@0 | 428 | rect.height = height; |
michael@0 | 429 | page->SetRect(rect); |
michael@0 | 430 | y += rect.height + mMargin.top + mMargin.bottom; |
michael@0 | 431 | } |
michael@0 | 432 | pageNum++; |
michael@0 | 433 | } |
michael@0 | 434 | |
michael@0 | 435 | // adjust total number of pages |
michael@0 | 436 | if (nsIPrintSettings::kRangeSelection != mPrintRangeType) { |
michael@0 | 437 | totalPages = pageNum - 1; |
michael@0 | 438 | } |
michael@0 | 439 | } |
michael@0 | 440 | |
michael@0 | 441 | mPageNum = 1; |
michael@0 | 442 | |
michael@0 | 443 | if (mTotalPages == -1) { |
michael@0 | 444 | mTotalPages = totalPages; |
michael@0 | 445 | } |
michael@0 | 446 | |
michael@0 | 447 | return rv; |
michael@0 | 448 | } |
michael@0 | 449 | |
michael@0 | 450 | void |
michael@0 | 451 | GetPrintCanvasElementsInFrame(nsIFrame* aFrame, nsTArray<nsRefPtr<HTMLCanvasElement> >* aArr) |
michael@0 | 452 | { |
michael@0 | 453 | if (!aFrame) { |
michael@0 | 454 | return; |
michael@0 | 455 | } |
michael@0 | 456 | for (nsIFrame::ChildListIterator childLists(aFrame); |
michael@0 | 457 | !childLists.IsDone(); childLists.Next()) { |
michael@0 | 458 | |
michael@0 | 459 | nsFrameList children = childLists.CurrentList(); |
michael@0 | 460 | for (nsFrameList::Enumerator e(children); !e.AtEnd(); e.Next()) { |
michael@0 | 461 | nsIFrame* child = e.get(); |
michael@0 | 462 | |
michael@0 | 463 | // Check if child is a nsHTMLCanvasFrame. |
michael@0 | 464 | nsHTMLCanvasFrame* canvasFrame = do_QueryFrame(child); |
michael@0 | 465 | |
michael@0 | 466 | // If there is a canvasFrame, try to get actual canvas element. |
michael@0 | 467 | if (canvasFrame) { |
michael@0 | 468 | HTMLCanvasElement* canvas = |
michael@0 | 469 | HTMLCanvasElement::FromContentOrNull(canvasFrame->GetContent()); |
michael@0 | 470 | if (canvas && canvas->GetMozPrintCallback()) { |
michael@0 | 471 | aArr->AppendElement(canvas); |
michael@0 | 472 | continue; |
michael@0 | 473 | } |
michael@0 | 474 | } |
michael@0 | 475 | |
michael@0 | 476 | if (!child->GetFirstPrincipalChild()) { |
michael@0 | 477 | nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(child); |
michael@0 | 478 | if (subdocumentFrame) { |
michael@0 | 479 | // Descend into the subdocument |
michael@0 | 480 | nsIFrame* root = subdocumentFrame->GetSubdocumentRootFrame(); |
michael@0 | 481 | child = root; |
michael@0 | 482 | } |
michael@0 | 483 | } |
michael@0 | 484 | // The current child is not a nsHTMLCanvasFrame OR it is but there is |
michael@0 | 485 | // no HTMLCanvasElement on it. Check if children of `child` might |
michael@0 | 486 | // contain a HTMLCanvasElement. |
michael@0 | 487 | GetPrintCanvasElementsInFrame(child, aArr); |
michael@0 | 488 | } |
michael@0 | 489 | } |
michael@0 | 490 | } |
michael@0 | 491 | |
michael@0 | 492 | void |
michael@0 | 493 | nsSimplePageSequenceFrame::DetermineWhetherToPrintPage() |
michael@0 | 494 | { |
michael@0 | 495 | // See whether we should print this page |
michael@0 | 496 | mPrintThisPage = true; |
michael@0 | 497 | bool printEvenPages, printOddPages; |
michael@0 | 498 | mPageData->mPrintSettings->GetPrintOptions(nsIPrintSettings::kPrintEvenPages, &printEvenPages); |
michael@0 | 499 | mPageData->mPrintSettings->GetPrintOptions(nsIPrintSettings::kPrintOddPages, &printOddPages); |
michael@0 | 500 | |
michael@0 | 501 | // If printing a range of pages check whether the page number is in the |
michael@0 | 502 | // range of pages to print |
michael@0 | 503 | if (mDoingPageRange) { |
michael@0 | 504 | if (mPageNum < mFromPageNum) { |
michael@0 | 505 | mPrintThisPage = false; |
michael@0 | 506 | } else if (mPageNum > mToPageNum) { |
michael@0 | 507 | mPageNum++; |
michael@0 | 508 | mPrintThisPage = false; |
michael@0 | 509 | return; |
michael@0 | 510 | } else { |
michael@0 | 511 | int32_t length = mPageRanges.Length(); |
michael@0 | 512 | |
michael@0 | 513 | // Page ranges are pairs (start, end) |
michael@0 | 514 | if (length && (length % 2 == 0)) { |
michael@0 | 515 | mPrintThisPage = false; |
michael@0 | 516 | |
michael@0 | 517 | int32_t i; |
michael@0 | 518 | for (i = 0; i < length; i += 2) { |
michael@0 | 519 | if (mPageRanges[i] <= mPageNum && mPageNum <= mPageRanges[i+1]) { |
michael@0 | 520 | mPrintThisPage = true; |
michael@0 | 521 | break; |
michael@0 | 522 | } |
michael@0 | 523 | } |
michael@0 | 524 | } |
michael@0 | 525 | } |
michael@0 | 526 | } |
michael@0 | 527 | |
michael@0 | 528 | // Check for printing of odd and even pages |
michael@0 | 529 | if (mPageNum & 0x1) { |
michael@0 | 530 | if (!printOddPages) { |
michael@0 | 531 | mPrintThisPage = false; // don't print odd numbered page |
michael@0 | 532 | } |
michael@0 | 533 | } else { |
michael@0 | 534 | if (!printEvenPages) { |
michael@0 | 535 | mPrintThisPage = false; // don't print even numbered page |
michael@0 | 536 | } |
michael@0 | 537 | } |
michael@0 | 538 | |
michael@0 | 539 | if (nsIPrintSettings::kRangeSelection == mPrintRangeType) { |
michael@0 | 540 | mPrintThisPage = true; |
michael@0 | 541 | } |
michael@0 | 542 | } |
michael@0 | 543 | |
michael@0 | 544 | nsIFrame* |
michael@0 | 545 | nsSimplePageSequenceFrame::GetCurrentPageFrame() |
michael@0 | 546 | { |
michael@0 | 547 | int32_t i = 1; |
michael@0 | 548 | for (nsFrameList::Enumerator childFrames(mFrames); !childFrames.AtEnd(); |
michael@0 | 549 | childFrames.Next()) { |
michael@0 | 550 | if (i == mPageNum) { |
michael@0 | 551 | return childFrames.get(); |
michael@0 | 552 | } |
michael@0 | 553 | ++i; |
michael@0 | 554 | } |
michael@0 | 555 | return nullptr; |
michael@0 | 556 | } |
michael@0 | 557 | |
michael@0 | 558 | NS_IMETHODIMP |
michael@0 | 559 | nsSimplePageSequenceFrame::PrePrintNextPage(nsITimerCallback* aCallback, bool* aDone) |
michael@0 | 560 | { |
michael@0 | 561 | nsIFrame* currentPage = GetCurrentPageFrame(); |
michael@0 | 562 | if (!currentPage) { |
michael@0 | 563 | *aDone = true; |
michael@0 | 564 | return NS_ERROR_FAILURE; |
michael@0 | 565 | } |
michael@0 | 566 | |
michael@0 | 567 | DetermineWhetherToPrintPage(); |
michael@0 | 568 | // Nothing to do if the current page doesn't get printed OR rendering to |
michael@0 | 569 | // preview. For preview, the `CallPrintCallback` is called from within the |
michael@0 | 570 | // HTMLCanvasElement::HandlePrintCallback. |
michael@0 | 571 | if (!mPrintThisPage || !PresContext()->IsRootPaginatedDocument()) { |
michael@0 | 572 | *aDone = true; |
michael@0 | 573 | return NS_OK; |
michael@0 | 574 | } |
michael@0 | 575 | |
michael@0 | 576 | // If the canvasList is null, then generate it and start the render |
michael@0 | 577 | // process for all the canvas. |
michael@0 | 578 | if (!mCurrentCanvasListSetup) { |
michael@0 | 579 | mCurrentCanvasListSetup = true; |
michael@0 | 580 | GetPrintCanvasElementsInFrame(currentPage, &mCurrentCanvasList); |
michael@0 | 581 | |
michael@0 | 582 | if (mCurrentCanvasList.Length() != 0) { |
michael@0 | 583 | nsresult rv = NS_OK; |
michael@0 | 584 | |
michael@0 | 585 | // Begin printing of the document |
michael@0 | 586 | nsDeviceContext *dc = PresContext()->DeviceContext(); |
michael@0 | 587 | PR_PL(("\n")); |
michael@0 | 588 | PR_PL(("***************** BeginPage *****************\n")); |
michael@0 | 589 | rv = dc->BeginPage(); |
michael@0 | 590 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 591 | |
michael@0 | 592 | mCalledBeginPage = true; |
michael@0 | 593 | |
michael@0 | 594 | nsRefPtr<nsRenderingContext> renderingContext = |
michael@0 | 595 | dc->CreateRenderingContext(); |
michael@0 | 596 | |
michael@0 | 597 | nsRefPtr<gfxASurface> renderingSurface = |
michael@0 | 598 | renderingContext->ThebesContext()->CurrentSurface(); |
michael@0 | 599 | NS_ENSURE_TRUE(renderingSurface, NS_ERROR_OUT_OF_MEMORY); |
michael@0 | 600 | |
michael@0 | 601 | for (int32_t i = mCurrentCanvasList.Length() - 1; i >= 0 ; i--) { |
michael@0 | 602 | HTMLCanvasElement* canvas = mCurrentCanvasList[i]; |
michael@0 | 603 | nsIntSize size = canvas->GetSize(); |
michael@0 | 604 | |
michael@0 | 605 | nsRefPtr<gfxASurface> printSurface = renderingSurface-> |
michael@0 | 606 | CreateSimilarSurface( |
michael@0 | 607 | gfxContentType::COLOR_ALPHA, |
michael@0 | 608 | size |
michael@0 | 609 | ); |
michael@0 | 610 | |
michael@0 | 611 | if (!printSurface) { |
michael@0 | 612 | continue; |
michael@0 | 613 | } |
michael@0 | 614 | |
michael@0 | 615 | nsICanvasRenderingContextInternal* ctx = canvas->GetContextAtIndex(0); |
michael@0 | 616 | |
michael@0 | 617 | if (!ctx) { |
michael@0 | 618 | continue; |
michael@0 | 619 | } |
michael@0 | 620 | |
michael@0 | 621 | // Initialize the context with the new printSurface. |
michael@0 | 622 | ctx->InitializeWithSurface(nullptr, printSurface, size.width, size.height); |
michael@0 | 623 | |
michael@0 | 624 | // Start the rendering process. |
michael@0 | 625 | nsWeakFrame weakFrame = this; |
michael@0 | 626 | canvas->DispatchPrintCallback(aCallback); |
michael@0 | 627 | NS_ENSURE_STATE(weakFrame.IsAlive()); |
michael@0 | 628 | } |
michael@0 | 629 | } |
michael@0 | 630 | } |
michael@0 | 631 | uint32_t doneCounter = 0; |
michael@0 | 632 | for (int32_t i = mCurrentCanvasList.Length() - 1; i >= 0 ; i--) { |
michael@0 | 633 | HTMLCanvasElement* canvas = mCurrentCanvasList[i]; |
michael@0 | 634 | |
michael@0 | 635 | if (canvas->IsPrintCallbackDone()) { |
michael@0 | 636 | doneCounter++; |
michael@0 | 637 | } |
michael@0 | 638 | } |
michael@0 | 639 | // If all canvas have finished rendering, return true, otherwise false. |
michael@0 | 640 | *aDone = doneCounter == mCurrentCanvasList.Length(); |
michael@0 | 641 | |
michael@0 | 642 | return NS_OK; |
michael@0 | 643 | } |
michael@0 | 644 | |
michael@0 | 645 | NS_IMETHODIMP |
michael@0 | 646 | nsSimplePageSequenceFrame::ResetPrintCanvasList() |
michael@0 | 647 | { |
michael@0 | 648 | for (int32_t i = mCurrentCanvasList.Length() - 1; i >= 0 ; i--) { |
michael@0 | 649 | HTMLCanvasElement* canvas = mCurrentCanvasList[i]; |
michael@0 | 650 | canvas->ResetPrintCallback(); |
michael@0 | 651 | } |
michael@0 | 652 | |
michael@0 | 653 | mCurrentCanvasList.Clear(); |
michael@0 | 654 | mCurrentCanvasListSetup = false; |
michael@0 | 655 | return NS_OK; |
michael@0 | 656 | } |
michael@0 | 657 | |
michael@0 | 658 | NS_IMETHODIMP |
michael@0 | 659 | nsSimplePageSequenceFrame::PrintNextPage() |
michael@0 | 660 | { |
michael@0 | 661 | // Print each specified page |
michael@0 | 662 | // pageNum keeps track of the current page and what pages are printing |
michael@0 | 663 | // |
michael@0 | 664 | // printedPageNum keeps track of the current page number to be printed |
michael@0 | 665 | // Note: When print al the pages or a page range the printed page shows the |
michael@0 | 666 | // actual page number, when printing selection it prints the page number starting |
michael@0 | 667 | // with the first page of the selection. For example if the user has a |
michael@0 | 668 | // selection that starts on page 2 and ends on page 3, the page numbers when |
michael@0 | 669 | // print are 1 and then two (which is different than printing a page range, where |
michael@0 | 670 | // the page numbers would have been 2 and then 3) |
michael@0 | 671 | |
michael@0 | 672 | nsIFrame* currentPage = GetCurrentPageFrame(); |
michael@0 | 673 | if (!currentPage) { |
michael@0 | 674 | return NS_ERROR_FAILURE; |
michael@0 | 675 | } |
michael@0 | 676 | |
michael@0 | 677 | nsresult rv = NS_OK; |
michael@0 | 678 | |
michael@0 | 679 | DetermineWhetherToPrintPage(); |
michael@0 | 680 | |
michael@0 | 681 | if (mPrintThisPage) { |
michael@0 | 682 | // Begin printing of the document |
michael@0 | 683 | nsDeviceContext* dc = PresContext()->DeviceContext(); |
michael@0 | 684 | |
michael@0 | 685 | // XXX This is temporary fix for printing more than one page of a selection |
michael@0 | 686 | // This does a poor man's "dump" pagination (see Bug 89353) |
michael@0 | 687 | // It has laid out as one long page and now we are just moving or view up/down |
michael@0 | 688 | // one page at a time and printing the contents of what is exposed by the rect. |
michael@0 | 689 | // currently this does not work for IFrames |
michael@0 | 690 | // I will soon improve this to work with IFrames |
michael@0 | 691 | bool continuePrinting = true; |
michael@0 | 692 | nscoord width, height; |
michael@0 | 693 | width = PresContext()->GetPageSize().width; |
michael@0 | 694 | height = PresContext()->GetPageSize().height; |
michael@0 | 695 | height -= mMargin.top + mMargin.bottom; |
michael@0 | 696 | width -= mMargin.left + mMargin.right; |
michael@0 | 697 | nscoord selectionY = height; |
michael@0 | 698 | nsIFrame* conFrame = currentPage->GetFirstPrincipalChild(); |
michael@0 | 699 | if (mSelectionHeight >= 0) { |
michael@0 | 700 | conFrame->SetPosition(conFrame->GetPosition() + nsPoint(0, -mYSelOffset)); |
michael@0 | 701 | nsContainerFrame::PositionChildViews(conFrame); |
michael@0 | 702 | } |
michael@0 | 703 | |
michael@0 | 704 | // cast the frame to be a page frame |
michael@0 | 705 | nsPageFrame * pf = static_cast<nsPageFrame*>(currentPage); |
michael@0 | 706 | pf->SetPageNumInfo(mPageNum, mTotalPages); |
michael@0 | 707 | pf->SetSharedPageData(mPageData); |
michael@0 | 708 | |
michael@0 | 709 | int32_t printedPageNum = 1; |
michael@0 | 710 | while (continuePrinting) { |
michael@0 | 711 | if (PresContext()->IsRootPaginatedDocument()) { |
michael@0 | 712 | if (!mCalledBeginPage) { |
michael@0 | 713 | PR_PL(("\n")); |
michael@0 | 714 | PR_PL(("***************** BeginPage *****************\n")); |
michael@0 | 715 | rv = dc->BeginPage(); |
michael@0 | 716 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 717 | } else { |
michael@0 | 718 | mCalledBeginPage = false; |
michael@0 | 719 | } |
michael@0 | 720 | } |
michael@0 | 721 | |
michael@0 | 722 | PR_PL(("SeqFr::PrintNextPage -> %p PageNo: %d", pf, mPageNum)); |
michael@0 | 723 | |
michael@0 | 724 | nsRefPtr<nsRenderingContext> renderingContext = |
michael@0 | 725 | dc->CreateRenderingContext(); |
michael@0 | 726 | |
michael@0 | 727 | nsRect drawingRect(nsPoint(0, 0), currentPage->GetSize()); |
michael@0 | 728 | nsRegion drawingRegion(drawingRect); |
michael@0 | 729 | nsLayoutUtils::PaintFrame(renderingContext, currentPage, |
michael@0 | 730 | drawingRegion, NS_RGBA(0,0,0,0), |
michael@0 | 731 | nsLayoutUtils::PAINT_SYNC_DECODE_IMAGES); |
michael@0 | 732 | |
michael@0 | 733 | if (mSelectionHeight >= 0 && selectionY < mSelectionHeight) { |
michael@0 | 734 | selectionY += height; |
michael@0 | 735 | printedPageNum++; |
michael@0 | 736 | pf->SetPageNumInfo(printedPageNum, mTotalPages); |
michael@0 | 737 | conFrame->SetPosition(conFrame->GetPosition() + nsPoint(0, -height)); |
michael@0 | 738 | nsContainerFrame::PositionChildViews(conFrame); |
michael@0 | 739 | |
michael@0 | 740 | PR_PL(("***************** End Page (PrintNextPage) *****************\n")); |
michael@0 | 741 | rv = dc->EndPage(); |
michael@0 | 742 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 743 | } else { |
michael@0 | 744 | continuePrinting = false; |
michael@0 | 745 | } |
michael@0 | 746 | } |
michael@0 | 747 | } |
michael@0 | 748 | return rv; |
michael@0 | 749 | } |
michael@0 | 750 | |
michael@0 | 751 | NS_IMETHODIMP |
michael@0 | 752 | nsSimplePageSequenceFrame::DoPageEnd() |
michael@0 | 753 | { |
michael@0 | 754 | nsresult rv = NS_OK; |
michael@0 | 755 | if (PresContext()->IsRootPaginatedDocument() && mPrintThisPage) { |
michael@0 | 756 | PR_PL(("***************** End Page (DoPageEnd) *****************\n")); |
michael@0 | 757 | rv = PresContext()->DeviceContext()->EndPage(); |
michael@0 | 758 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 759 | } |
michael@0 | 760 | |
michael@0 | 761 | ResetPrintCanvasList(); |
michael@0 | 762 | |
michael@0 | 763 | mPageNum++; |
michael@0 | 764 | |
michael@0 | 765 | return rv; |
michael@0 | 766 | } |
michael@0 | 767 | |
michael@0 | 768 | static gfx3DMatrix |
michael@0 | 769 | ComputePageSequenceTransform(nsIFrame* aFrame, float aAppUnitsPerPixel) |
michael@0 | 770 | { |
michael@0 | 771 | float scale = aFrame->PresContext()->GetPrintPreviewScale(); |
michael@0 | 772 | return gfx3DMatrix::ScalingMatrix(scale, scale, 1); |
michael@0 | 773 | } |
michael@0 | 774 | |
michael@0 | 775 | void |
michael@0 | 776 | nsSimplePageSequenceFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, |
michael@0 | 777 | const nsRect& aDirtyRect, |
michael@0 | 778 | const nsDisplayListSet& aLists) |
michael@0 | 779 | { |
michael@0 | 780 | DisplayBorderBackgroundOutline(aBuilder, aLists); |
michael@0 | 781 | |
michael@0 | 782 | nsDisplayList content; |
michael@0 | 783 | |
michael@0 | 784 | { |
michael@0 | 785 | // Clear clip state while we construct the children of the |
michael@0 | 786 | // nsDisplayTransform, since they'll be in a different coordinate system. |
michael@0 | 787 | DisplayListClipState::AutoSaveRestore clipState(aBuilder); |
michael@0 | 788 | clipState.Clear(); |
michael@0 | 789 | |
michael@0 | 790 | nsIFrame* child = GetFirstPrincipalChild(); |
michael@0 | 791 | while (child) { |
michael@0 | 792 | child->BuildDisplayListForStackingContext(aBuilder, |
michael@0 | 793 | child->GetVisualOverflowRectRelativeToSelf(), &content); |
michael@0 | 794 | aBuilder->ResetMarkedFramesForDisplayList(); |
michael@0 | 795 | child = child->GetNextSibling(); |
michael@0 | 796 | } |
michael@0 | 797 | } |
michael@0 | 798 | |
michael@0 | 799 | content.AppendNewToTop(new (aBuilder) |
michael@0 | 800 | nsDisplayTransform(aBuilder, this, &content, ::ComputePageSequenceTransform)); |
michael@0 | 801 | |
michael@0 | 802 | aLists.Content()->AppendToTop(&content); |
michael@0 | 803 | } |
michael@0 | 804 | |
michael@0 | 805 | nsIAtom* |
michael@0 | 806 | nsSimplePageSequenceFrame::GetType() const |
michael@0 | 807 | { |
michael@0 | 808 | return nsGkAtoms::sequenceFrame; |
michael@0 | 809 | } |
michael@0 | 810 | |
michael@0 | 811 | //------------------------------------------------------------------------------ |
michael@0 | 812 | void |
michael@0 | 813 | nsSimplePageSequenceFrame::SetPageNumberFormat(const nsAString& aFormatStr, bool aForPageNumOnly) |
michael@0 | 814 | { |
michael@0 | 815 | NS_ASSERTION(mPageData != nullptr, "mPageData string cannot be null!"); |
michael@0 | 816 | |
michael@0 | 817 | if (aForPageNumOnly) { |
michael@0 | 818 | mPageData->mPageNumFormat = aFormatStr; |
michael@0 | 819 | } else { |
michael@0 | 820 | mPageData->mPageNumAndTotalsFormat = aFormatStr; |
michael@0 | 821 | } |
michael@0 | 822 | } |
michael@0 | 823 | |
michael@0 | 824 | //------------------------------------------------------------------------------ |
michael@0 | 825 | void |
michael@0 | 826 | nsSimplePageSequenceFrame::SetDateTimeStr(const nsAString& aDateTimeStr) |
michael@0 | 827 | { |
michael@0 | 828 | NS_ASSERTION(mPageData != nullptr, "mPageData string cannot be null!"); |
michael@0 | 829 | |
michael@0 | 830 | mPageData->mDateTimeStr = aDateTimeStr; |
michael@0 | 831 | } |
michael@0 | 832 | |
michael@0 | 833 | //------------------------------------------------------------------------------ |
michael@0 | 834 | // For Shrink To Fit |
michael@0 | 835 | // |
michael@0 | 836 | // Return the percentage that the page needs to shrink to |
michael@0 | 837 | // |
michael@0 | 838 | NS_IMETHODIMP |
michael@0 | 839 | nsSimplePageSequenceFrame::GetSTFPercent(float& aSTFPercent) |
michael@0 | 840 | { |
michael@0 | 841 | NS_ENSURE_TRUE(mPageData, NS_ERROR_UNEXPECTED); |
michael@0 | 842 | aSTFPercent = mPageData->mShrinkToFitRatio; |
michael@0 | 843 | return NS_OK; |
michael@0 | 844 | } |