Changeset 76470 in webkit


Ignore:
Timestamp:
Jan 23, 2011 2:28:01 PM (13 years ago)
Author:
ap@apple.com
Message:

2011-01-23 Alexey Proskuryakov <ap@apple.com>

Reviewed by Dan Bernstein.

https://bugs.webkit.org/show_bug.cgi?id=52968
Use a separate NSView for printing

Also addresses <rdar://problem/8900148> Improper check for
-[NSGraphicsContext currentContextDrawingToScreen]

  • UIProcess/API/mac/WKPrintingView.h: Added.
  • UIProcess/API/mac/WKPrintingView.mm: Added. (-[WKPrintingView initWithFrameProxy:]): (-[WKPrintingView isFlipped]): (-[WKPrintingView _adjustPrintingMarginsForHeaderAndFooter]): (-[WKPrintingView knowsPageRange:]): (-[WKPrintingView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]): (-[WKPrintingView drawPageBorderWithSize:]): (-[WKPrintingView _provideTotalScaleFactorForPrintOperation:]): (-[WKPrintingView rectForPage:]):
  • UIProcess/API/mac/WKView.mm: (-[WKView drawRect:]): (-[WKView canChangeFrameLayout:]): (-[WKView printOperationWithPrintInfo:forFrame:]):
  • WebKit2.xcodeproj/project.pbxproj: Moved printing code to a separate view, simplifying as appropriate. The view is currently not referenced by anything in WebKit2 directly, being owned by NSPrintOperation.
Location:
trunk/Source/WebKit2
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r76453 r76470  
     12011-01-23  Alexey Proskuryakov  <ap@apple.com>
     2
     3        Reviewed by Dan Bernstein.
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=52968
     6        Use a separate NSView for printing
     7
     8        Also addresses <rdar://problem/8900148> Improper check for
     9        -[NSGraphicsContext currentContextDrawingToScreen]
     10
     11        * UIProcess/API/mac/WKPrintingView.h: Added.
     12        * UIProcess/API/mac/WKPrintingView.mm: Added.
     13        (-[WKPrintingView initWithFrameProxy:]):
     14        (-[WKPrintingView isFlipped]):
     15        (-[WKPrintingView _adjustPrintingMarginsForHeaderAndFooter]):
     16        (-[WKPrintingView knowsPageRange:]):
     17        (-[WKPrintingView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]):
     18        (-[WKPrintingView drawPageBorderWithSize:]):
     19        (-[WKPrintingView _provideTotalScaleFactorForPrintOperation:]):
     20        (-[WKPrintingView rectForPage:]):
     21        * UIProcess/API/mac/WKView.mm:
     22        (-[WKView drawRect:]):
     23        (-[WKView canChangeFrameLayout:]):
     24        (-[WKView printOperationWithPrintInfo:forFrame:]):
     25        * WebKit2.xcodeproj/project.pbxproj:
     26        Moved printing code to a separate view, simplifying as appropriate. The view is currently not
     27        referenced by anything in WebKit2 directly, being owned by NSPrintOperation.
     28
    1292011-01-22  Anders Carlsson  <andersca@apple.com>
    230
  • trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm

    r76433 r76470  
    3737#import "PageClientImpl.h"
    3838#import "PasteboardTypes.h"
    39 #import "PrintInfo.h"
    4039#import "Region.h"
    4140#import "RunLoop.h"
     
    4342#import "TextCheckerState.h"
    4443#import "WKAPICast.h"
     44#import "WKPrintingView.h"
    4545#import "WKStringCF.h"
    4646#import "WKTextInputWindowController.h"
     
    7272@end
    7373
    74 @interface NSView (Details)
    75 - (void)_recursiveDisplayRectIfNeededIgnoringOpacity:(NSRect)rect isVisibleRect:(BOOL)isVisibleRect rectIsVisibleRectForView:(NSView *)visibleView topView:(BOOL)topView;
    76 @end
    77 
    7874@interface NSWindow (Details)
    7975- (NSRect)_growBoxRect;
     
    9793
    9894}
    99 
    100 NSString* const WebKitOriginalTopPrintingMarginKey = @"WebKitOriginalTopMargin";
    101 NSString* const WebKitOriginalBottomPrintingMarginKey = @"WebKitOriginalBottomMargin";
    10295
    10396@interface WKViewData : NSObject {
     
    136129    unsigned _selectionEnd;
    137130
    138     Vector<IntRect> _printingPageRects;
    139     double _totalScaleFactorForPrinting;
    140 
    141131    bool _inBecomeFirstResponder;
    142132    bool _inResignFirstResponder;
     
    149139@implementation WKViewData
    150140@end
    151 
    152 @interface WebFrameWrapper : NSObject {
    153 @public
    154     RefPtr<WebFrameProxy> _frame;
    155 }
    156 
    157 - (id)initWithFrameProxy:(WebFrameProxy*)frame;
    158 - (WebFrameProxy*)webFrame;
    159 @end
    160 
    161 @implementation WebFrameWrapper
    162 
    163 - (id)initWithFrameProxy:(WebFrameProxy*)frame
    164 {
    165     self = [super init];
    166     if (!self)
    167         return nil;
    168 
    169     _frame = frame;
    170     return self;
    171 }
    172 
    173 - (WebFrameProxy*)webFrame
    174 {
    175     return _frame.get();
    176 }
    177 
    178 @end
    179 
    180 NSString * const PrintedFrameKey = @"WebKitPrintedFrameKey";
    181141
    182142@interface NSObject (NSTextInputContextDetails)
     
    12681228{
    12691229    LOG(View, "drawRect: x:%g, y:%g, width:%g, height:%g", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
     1230    _data->_page->endPrinting();
    12701231    if (useNewDrawingArea()) {
    12711232        if (DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(_data->_page->drawingArea())) {
     
    13661327}
    13671328
    1368 static void setFrameBeingPrinted(NSPrintOperation *printOperation, WebFrameProxy* frame)
    1369 {
    1370     RetainPtr<WebFrameWrapper> frameWrapper(AdoptNS, [[WebFrameWrapper alloc] initWithFrameProxy:frame]);
    1371     [[[printOperation printInfo] dictionary] setObject:frameWrapper.get() forKey:PrintedFrameKey];
    1372 }
    1373 
    1374 static WebFrameProxy* frameBeingPrinted()
    1375 {
    1376     return [[[[[NSPrintOperation currentOperation] printInfo] dictionary] objectForKey:PrintedFrameKey] webFrame];
    1377 }
    1378 
    1379 static float currentPrintOperationScale()
    1380 {
    1381     ASSERT([NSPrintOperation currentOperation]);
    1382     ASSERT([[[[NSPrintOperation currentOperation] printInfo] dictionary] objectForKey:NSPrintScalingFactor]);
    1383     return [[[[[NSPrintOperation currentOperation] printInfo] dictionary] objectForKey:NSPrintScalingFactor] floatValue];
    1384 }
    1385 
    1386 - (void)_adjustPrintingMarginsForHeaderAndFooter
    1387 {
    1388     NSPrintOperation *printOperation = [NSPrintOperation currentOperation];
    1389     NSPrintInfo *info = [printOperation printInfo];
    1390     NSMutableDictionary *infoDictionary = [info dictionary];
    1391 
    1392     // We need to modify the top and bottom margins in the NSPrintInfo to account for the space needed by the
    1393     // header and footer. Because this method can be called more than once on the same NSPrintInfo (see 5038087),
    1394     // we stash away the unmodified top and bottom margins the first time this method is called, and we read from
    1395     // those stashed-away values on subsequent calls.
    1396     float originalTopMargin;
    1397     float originalBottomMargin;
    1398     NSNumber *originalTopMarginNumber = [infoDictionary objectForKey:WebKitOriginalTopPrintingMarginKey];
    1399     if (!originalTopMarginNumber) {
    1400         ASSERT(![infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey]);
    1401         originalTopMargin = [info topMargin];
    1402         originalBottomMargin = [info bottomMargin];
    1403         [infoDictionary setObject:[NSNumber numberWithFloat:originalTopMargin] forKey:WebKitOriginalTopPrintingMarginKey];
    1404         [infoDictionary setObject:[NSNumber numberWithFloat:originalBottomMargin] forKey:WebKitOriginalBottomPrintingMarginKey];
    1405     } else {
    1406         ASSERT([originalTopMarginNumber isKindOfClass:[NSNumber class]]);
    1407         ASSERT([[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] isKindOfClass:[NSNumber class]]);
    1408         originalTopMargin = [originalTopMarginNumber floatValue];
    1409         originalBottomMargin = [[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] floatValue];
    1410     }
    1411    
    1412     float scale = currentPrintOperationScale();
    1413     [info setTopMargin:originalTopMargin + _data->_page->headerHeight(frameBeingPrinted()) * scale];
    1414     [info setBottomMargin:originalBottomMargin + _data->_page->footerHeight(frameBeingPrinted()) * scale];
     1329
     1330- (BOOL)canChangeFrameLayout:(WKFrameRef)frameRef
     1331{
     1332    // PDF documents are already paginated, so we can't change them to add headers and footers.
     1333    return !toImpl(frameRef)->isMainFrame() || !_data->_pdfViewController;
    14151334}
    14161335
     
    14181337{
    14191338    LOG(View, "Creating an NSPrintOperation for frame '%s'", toImpl(frameRef)->url().utf8().data());
    1420     NSPrintOperation *printOperation;
    14211339
    14221340    // Only the top frame can currently contain a PDF view.
    14231341    if (_data->_pdfViewController) {
    1424         ASSERT(toImpl(frameRef)->isMainFrame());
    1425         printOperation = _data->_pdfViewController->makePrintOperation(printInfo);
    1426     } else
    1427         printOperation = [NSPrintOperation printOperationWithView:self printInfo:printInfo];
    1428 
    1429     setFrameBeingPrinted(printOperation, toImpl(frameRef));
    1430     return printOperation;
    1431 }
    1432 
    1433 - (BOOL)canChangeFrameLayout:(WKFrameRef)frameRef
    1434 {
    1435     // PDF documents are already paginated, so we can't change them to add headers and footers.
    1436     return !toImpl(frameRef)->isMainFrame() || !_data->_pdfViewController;
    1437 }
    1438 
    1439 // Return the number of pages available for printing
    1440 - (BOOL)knowsPageRange:(NSRangePointer)range
    1441 {
    1442     LOG(View, "knowsPageRange:");
    1443     WebFrameProxy* frame = frameBeingPrinted();
    1444     ASSERT(frame);
    1445 
    1446     if (frame->isMainFrame() && _data->_pdfViewController)
    1447         return [super knowsPageRange:range];
    1448 
    1449     [self _adjustPrintingMarginsForHeaderAndFooter];
    1450 
    1451     _data->_page->computePagesForPrinting(frame, PrintInfo([[NSPrintOperation currentOperation] printInfo]), _data->_printingPageRects, _data->_totalScaleFactorForPrinting);
    1452 
    1453     *range = NSMakeRange(1, _data->_printingPageRects.size());
    1454     return YES;
    1455 }
    1456 
    1457 // Take over printing. AppKit applies incorrect clipping, and doesn't print pages beyond the first one.
    1458 - (void)_recursiveDisplayRectIfNeededIgnoringOpacity:(NSRect)rect isVisibleRect:(BOOL)isVisibleRect rectIsVisibleRectForView:(NSView *)visibleView topView:(BOOL)topView
    1459 {
    1460     // FIXME: This check isn't right for some non-printing cases, such as capturing into a buffer using cacheDisplayInRect:toBitmapImageRep:.
    1461     if ([NSGraphicsContext currentContextDrawingToScreen]) {
    1462         _data->_page->endPrinting();
    1463         [super _recursiveDisplayRectIfNeededIgnoringOpacity:rect isVisibleRect:isVisibleRect rectIsVisibleRectForView:visibleView topView:topView];
    1464         return;
    1465     }
    1466 
    1467     LOG(View, "Printing rect x:%g, y:%g, width:%g, height:%g", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
    1468 
    1469     ASSERT(self == visibleView);
    1470     ASSERT(frameBeingPrinted());
    1471 
    1472     WebFrameProxy* frame = frameBeingPrinted();
    1473     ASSERT(frame);
    1474 
    1475     _data->_page->beginPrinting(frame, PrintInfo([[NSPrintOperation currentOperation] printInfo]));
    1476 
    1477     // FIXME: This is optimized for print preview. Get the whole document at once when actually printing.
    1478     Vector<uint8_t> pdfData;
    1479     _data->_page->drawRectToPDF(frame, IntRect(rect), pdfData);
    1480 
    1481     RetainPtr<CGDataProviderRef> pdfDataProvider(AdoptCF, CGDataProviderCreateWithData(0, pdfData.data(), pdfData.size(), 0));
    1482     RetainPtr<CGPDFDocumentRef> pdfDocument(AdoptCF, CGPDFDocumentCreateWithProvider(pdfDataProvider.get()));
    1483     if (!pdfDocument) {
    1484         LOG_ERROR("Couldn't create a PDF document with data passed for printing");
    1485         return;
    1486     }
    1487 
    1488     CGPDFPageRef pdfPage = CGPDFDocumentGetPage(pdfDocument.get(), 1);
    1489     if (!pdfPage) {
    1490         LOG_ERROR("Printing data doesn't have page 1");
    1491         return;
    1492     }
    1493 
    1494     NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext];
    1495     CGContextRef context = static_cast<CGContextRef>([nsGraphicsContext graphicsPort]);
    1496 
    1497     CGContextSaveGState(context);
    1498     // Flip the destination.
    1499     CGContextScaleCTM(context, 1, -1);
    1500     CGContextTranslateCTM(context, 0, -CGPDFPageGetBoxRect(pdfPage, kCGPDFMediaBox).size.height);
    1501     CGContextDrawPDFPage(context, pdfPage);
    1502     CGContextRestoreGState(context);
    1503 }
    1504 
    1505 - (void)drawPageBorderWithSize:(NSSize)borderSize
    1506 {
    1507     ASSERT(NSEqualSizes(borderSize, [[[NSPrintOperation currentOperation] printInfo] paperSize]));   
    1508 
    1509     // The header and footer rect height scales with the page, but the width is always
    1510     // all the way across the printed page (inset by printing margins).
    1511     NSPrintOperation *printOperation = [NSPrintOperation currentOperation];
    1512     NSPrintInfo *printInfo = [printOperation printInfo];
    1513     float scale = currentPrintOperationScale();
    1514     NSSize paperSize = [printInfo paperSize];
    1515     float headerFooterLeft = [printInfo leftMargin] / scale;
    1516     float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin])) / scale;
    1517     WebFrameProxy* frame = frameBeingPrinted();
    1518     NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin] / scale - _data->_page->footerHeight(frame), headerFooterWidth, _data->_page->footerHeight(frame));
    1519     NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin]) / scale, headerFooterWidth, _data->_page->headerHeight(frame));
    1520 
    1521     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
    1522     [currentContext saveGraphicsState];
    1523     NSRectClip(headerRect);
    1524     _data->_page->drawHeader(frame, headerRect);
    1525     [currentContext restoreGraphicsState];
    1526 
    1527     [currentContext saveGraphicsState];
    1528     NSRectClip(footerRect);
    1529     _data->_page->drawFooter(frame, footerRect);
    1530     [currentContext restoreGraphicsState];
    1531 }
    1532 
    1533 // FIXME 3491344: This is an AppKit-internal method that we need to override in order
    1534 // to get our shrink-to-fit to work with a custom pagination scheme. We can do this better
    1535 // if AppKit makes it SPI/API.
    1536 - (CGFloat)_provideTotalScaleFactorForPrintOperation:(NSPrintOperation *)printOperation
    1537 {
    1538     return _data->_totalScaleFactorForPrinting;
    1539 }
    1540 
    1541 // Return the drawing rectangle for a particular page number
    1542 - (NSRect)rectForPage:(NSInteger)page
    1543 {
    1544     WebFrameProxy* frame = frameBeingPrinted();
    1545     ASSERT(frame);
    1546 
    1547     if (frame->isMainFrame() && _data->_pdfViewController)
    1548         return [super rectForPage:page];
    1549 
    1550     LOG(View, "rectForPage:%d -> x %d, y %d, width %d, height %d\n", (int)page, _data->_printingPageRects[page - 1].x(), _data->_printingPageRects[page - 1].y(), _data->_printingPageRects[page - 1].width(), _data->_printingPageRects[page - 1].height());
    1551     return _data->_printingPageRects[page - 1];
     1342        if (!toImpl(frameRef)->isMainFrame())
     1343            return 0;
     1344        return _data->_pdfViewController->makePrintOperation(printInfo);
     1345    } else {
     1346        RetainPtr<WKPrintingView> printingView(AdoptNS, [[WKPrintingView alloc] initWithFrameProxy:toImpl(frameRef)]);
     1347        // NSPrintOperation takes ownership of the view.
     1348        return [NSPrintOperation printOperationWithView:printingView.get()];
     1349    }
    15521350}
    15531351
  • trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj

    r76186 r76470  
    669669                D3B9484811FF4B6500032B39 /* WebSearchPopupMenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3B9484411FF4B6500032B39 /* WebSearchPopupMenu.cpp */; };
    670670                D3B9484911FF4B6500032B39 /* WebSearchPopupMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = D3B9484511FF4B6500032B39 /* WebSearchPopupMenu.h */; };
     671                E134F01712EA5D33004EC58D /* WKPrintingView.h in Headers */ = {isa = PBXBuildFile; fileRef = E134F01512EA5D11004EC58D /* WKPrintingView.h */; };
     672                E134F01A12EA5D99004EC58D /* WKPrintingView.mm in Sources */ = {isa = PBXBuildFile; fileRef = E134F01912EA5D99004EC58D /* WKPrintingView.mm */; };
    671673                E18C92F412DB9E7100CF2AEB /* PrintInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E18C92F312DB9E7100CF2AEB /* PrintInfo.cpp */; };
    672674                E18C92F512DB9E7A00CF2AEB /* PrintInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E18C92F312DB9E7100CF2AEB /* PrintInfo.cpp */; };
     
    14321434                D3B9484411FF4B6500032B39 /* WebSearchPopupMenu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSearchPopupMenu.cpp; sourceTree = "<group>"; };
    14331435                D3B9484511FF4B6500032B39 /* WebSearchPopupMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSearchPopupMenu.h; sourceTree = "<group>"; };
     1436                E134F01512EA5D11004EC58D /* WKPrintingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKPrintingView.h; sourceTree = "<group>"; };
     1437                E134F01912EA5D99004EC58D /* WKPrintingView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKPrintingView.mm; sourceTree = "<group>"; };
    14341438                E18C92F312DB9E7100CF2AEB /* PrintInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrintInfo.cpp; sourceTree = "<group>"; };
    14351439                E1CC1B8E12D7EADF00625838 /* PrintInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrintInfo.h; sourceTree = "<group>"; };
     
    23182322                                BC111B4B112F619200337BAB /* PageClientImpl.h */,
    23192323                                BC111B4C112F619200337BAB /* PageClientImpl.mm */,
     2324                                E134F01512EA5D11004EC58D /* WKPrintingView.h */,
     2325                                E134F01912EA5D99004EC58D /* WKPrintingView.mm */,
    23202326                                1A4A9AA612B7E796008FE984 /* WKTextInputWindowController.h */,
    23212327                                1A4A9AA712B7E796008FE984 /* WKTextInputWindowController.mm */,
     
    30703076                                1AA2E51D12E4C05E00BC4966 /* CGUtilities.h in Headers */,
    30713077                                C574A58112E66681002DFE98 /* PasteboardTypes.h in Headers */,
     3078                                E134F01712EA5D33004EC58D /* WKPrintingView.h in Headers */,
    30723079                        );
    30733080                        runOnlyForDeploymentPostprocessing = 0;
     
    35333540                                C574A37712E6099D002DFE98 /* WebDragClientMac.mm in Sources */,
    35343541                                C574A58212E66681002DFE98 /* PasteboardTypes.mm in Sources */,
     3542                                E134F01A12EA5D99004EC58D /* WKPrintingView.mm in Sources */,
    35353543                        );
    35363544                        runOnlyForDeploymentPostprocessing = 0;
Note: See TracChangeset for help on using the changeset viewer.