Simple printint implementation

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@11341 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Adam Fedor 2001-11-08 18:26:39 +00:00
parent 81915f4a3c
commit 04a3436aff
119 changed files with 4892 additions and 3621 deletions

View file

@ -45,6 +45,9 @@ static BOOL boldSystemCacheNeedsRecomputing = NO;
static BOOL userCacheNeedsRecomputing = NO;
static BOOL userFixedCacheNeedsRecomputing = NO;
/* Set used to keep track of fonts we are using */
static NSMutableSet *usedFonts = nil;
@interface NSFont (Private)
- (id) initWithName: (NSString*)name
matrix: (const float*)fontMatrix;
@ -394,9 +397,21 @@ setNSFont(NSString* key, NSFont* font)
+ (void) useFont: (NSString*)name
{
NSGraphicsContext *ctxt = GSCurrentContext();
if (usedFonts == nil)
usedFonts = RETAIN([NSMutableSet setWithCapacity: 2]);
[ctxt useFont: name];
[usedFonts addObject: name];
}
+ (void) resetUsedFonts
{
if (usedFonts)
[usedFonts removeAllObjects];
}
+ (NSSet *) usedFonts
{
return usedFonts;
}
//
@ -497,7 +512,7 @@ setNSFont(NSString* key, NSFont* font)
NSGraphicsContext *ctxt = GSCurrentContext();
[ctxt setFont: self];
[ctxt useFont: fontName];
[NSFont useFont: fontName];
}
//

View file

@ -111,18 +111,6 @@ NSGraphicsContext *GSCurrentContext()
defaultNSGraphicsContextClass = defaultContextClass;
}
+ defaultContextWithInfo: (NSDictionary *)info;
{
NSGraphicsContext *ctxt;
NSAssert(defaultNSGraphicsContextClass,
@"Internal Error: No default NSGraphicsContext set\n");
ctxt = [[defaultNSGraphicsContextClass allocWithZone: _globalGSZone]
initWithContextInfo: info];
AUTORELEASE(ctxt);
return ctxt;
}
+ (void) setCurrentContext: (NSGraphicsContext *)context
{
#ifdef GNUSTEP_BASE_LIBRARY
@ -149,10 +137,25 @@ NSGraphicsContext *GSCurrentContext()
return [GSCurrentContext() isDrawingToScreen];
}
+ (NSGraphicsContext *) graphicsContextWithAttributes: (NSDictionary *)attributes
+ defaultContextWithInfo: (NSDictionary *)info;
{
// FIXME: The attributes should determine the concrete class
return [self defaultContextWithInfo: attributes];
return [self graphicsContextWithAttributes: info];
}
+ (NSGraphicsContext *) graphicsContextWithAttributes: (NSDictionary *)info
{
NSGraphicsContext *ctxt;
if (self == [NSGraphicsContext class])
{
NSAssert(defaultNSGraphicsContextClass,
@"Internal Error: No default NSGraphicsContext set\n");
ctxt = [[defaultNSGraphicsContextClass allocWithZone: _globalGSZone]
initWithContextInfo: info];
AUTORELEASE(ctxt);
}
else
ctxt = [[self allocWithZone: _globalGSZone] initWithContextInfo: info];
return ctxt;
}
+ (NSGraphicsContext *) graphicsContextWithWindow: (NSWindow *)aWindow
@ -1170,16 +1173,6 @@ NSGraphicsContext *GSCurrentContext()
[self subclassResponsibility: _cmd];
}
- (void) useFont: (NSString*) name
{
/*
* Do nothing here, printing subclasses will have to register all
* the fonts used by the current print operation to be able to
* dump the %%DocumentFonts comment required by the Adobe Document
* Structuring Convention (see the red book).
*/
}
/* ----------------------------------------------------------------------- */
/* Gstate operations */
/* ----------------------------------------------------------------------- */

View file

@ -194,7 +194,6 @@ static NSPageLayout *shared_instance;
result = [NSApp runModalForWindow: self];
[self orderOut: self];
NSLog(@"Model Page Layout ended with code %d", result);
return result;
}
@ -486,8 +485,7 @@ static NSPageLayout *shared_instance;
[_printInfo setOrientation: [control selectedColumn]+NSPortraitOrientation];
/* Write Size */
/* FIXME: Currently don't allow writing size. What does that mean
anyway? Shouldn't we set margins instead? */
/* FIXME: Currently don't allow writing custom size. */
}

View file

@ -26,7 +26,9 @@
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <Foundation/NSArray.h>
#include <Foundation/NSBundle.h>
#include <Foundation/NSDebug.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSException.h>
#include <Foundation/NSEnumerator.h>
@ -47,6 +49,10 @@
#define NSPrintInfo_DEFAULTSTABLE @"PrintDefaults"
#endif
#define NSNUMBER(val) [NSNumber numberWithInt: val]
#define DICTSET(dict, obj, key) \
[dict setObject: obj forKey: key]
// FIXME: retain/release of dictionary with retain/release of printInfo?
// Class variables:
@ -58,6 +64,16 @@ NSDictionary *paperSizes = nil;
+ initPrintInfoDefaults;
@end
/**
<unit>
<heading>Class Description</heading>
<p>
NSPrintInfo is a storage object that stores information that describes
how a view is to printed and the destination information for printing.
</p>
</unit>
*/
@implementation NSPrintInfo
//
@ -98,28 +114,6 @@ NSDictionary *paperSizes = nil;
+ (NSSize)sizeForPaperName:(NSString *)name
{
return [[self defaultPrinter] pageSizeForPaper:name];
// Alternatively:
// NSBundle *adminBundle;
// NSString *path;
// NSValue *size;
// if (!paperSizes)
// {
// adminBundle = [NSBundle bundleWithPath:NSPrinterAdmin_PATH];
// path = [adminBundle pathForResource:NSPrintInfo_PAPERFILE ofType:nil];
// // If not found
// if (path == nil || [path length] == 0)
// {
// [NSException raise:NSGenericException
// format:@"Could not find paper size index, file %s",
// [NSPrintInfo_PAPERFILE cString]];
// // NOT REACHED
// }
// paperSizes = RETAIN([NSDictionary dictionaryWithContentsOfFile:path]);
// }
// size = [paperSizes objectForKey:name];
// if (!size)
// return NSZeroSize;
// return [size sizeValue];
}
//
@ -214,19 +208,41 @@ NSDictionary *paperSizes = nil;
- (void)setOrientation:(NSPrintingOrientation)mode
{
NSSize size;
[_info setObject:[NSNumber numberWithInt:mode]
forKey:NSPrintOrientation];
/* Set the paper size accordingly */
size = [self paperSize];
if ((mode == NSPortraitOrientation && size.width > size.height)
|| (mode == NSLandscapeOrientation && size.width < size.height))
{
float tmp = size.width;
size.width = size.height;
size.height = tmp;
[_info setObject: [NSValue valueWithSize: size]
forKey: NSPrintPaperSize];
}
}
- (void)setPaperName:(NSString *)name
{
[_info setObject:name forKey:NSPrintPaperName];
DICTSET(_info, name, NSPrintPaperName);
DICTSET(_info,
[NSValue valueWithSize: [NSPrintInfo sizeForPaperName: name]],
NSPrintPaperSize);
}
- (void)setPaperSize:(NSSize)size
{
NSPrintingOrientation orient;
[_info setObject:[NSValue valueWithSize:size]
forKey:NSPrintPaperSize];
/* Set orientation accordingly */
if (size.width <= size.height)
orient = NSPortraitOrientation;
else
orient = NSLandscapeOrientation;
DICTSET(_info, NSNUMBER(orient), NSPrintOrientation);
}
- (void)setRightMargin:(float)value
@ -369,38 +385,62 @@ NSDictionary *paperSizes = nil;
//
+ initPrintInfoDefaults
{
NSString *defPrinter, *str;
NSBundle *adminBundle;
NSString *path;
NSPrinter *printer;
adminBundle = [NSBundle bundleWithPath:NSPrinterAdmin_PATH];
path = [adminBundle pathForResource:NSPrintInfo_DEFAULTSTABLE ofType:nil];
// If not found
defPrinter = nil;
if (path != nil && [path length] != 0)
{
printInfoDefaults = RETAIN([NSMutableDictionary dictionaryWithContentsOfFile:path]);
// NOT REACHED
printInfoDefaults = [NSMutableDictionary dictionaryWithContentsOfFile:path];
RETAIN(printInfoDefaults);
defPrinter = [printInfoDefaults objectForKey:NSPrintPrinter];
printer = [NSPrinter printerWithName: defPrinter];
if (printer == nil)
defPrinter = nil;
}
if (printInfoDefaults == nil)
{
NSLog(@"Could not find printing defaults table, file %s",
[NSPrintInfo_DEFAULTSTABLE cString]);
// FIXME: As a replacement we add a very simple definition
printInfoDefaults = RETAIN(([NSMutableDictionary dictionaryWithObjectsAndKeys:
@"Unknown", NSPrintPrinter,
@"A4", NSPrintPaperName,
NULL]));
NSDebugLog(@"NSPrinter", @"Could not find printing defaults table, file %@",
NSPrintInfo_DEFAULTSTABLE);
printInfoDefaults = RETAIN([NSMutableDictionary dictionary]);
}
if (defPrinter == nil)
{
defPrinter = [[NSPrinter printerNames] objectAtIndex: 0];
DICTSET(printInfoDefaults, defPrinter, NSPrintPrinter);
}
// The loaded dictionary contains the name of the printer for NSPrintPrinter
// Load the real NSPrinter object...
[printInfoDefaults
setObject:[NSPrinter printerWithName:[printInfoDefaults
objectForKey:NSPrintPrinter]]
forKey:NSPrintPrinter];
[printInfoDefaults
setObject:[NSValue valueWithSize:
[NSPrintInfo sizeForPaperName:
[printInfoDefaults objectForKey:NSPrintPaperName]]]
forKey:NSPrintPaperSize];
/* Replace the printer name with a real NSPrinter object */
printer = [NSPrinter printerWithName: defPrinter];
DICTSET(printInfoDefaults, [NSPrinter printerWithName: defPrinter], NSPrintPrinter);
/* Set up other defaults from the printer object */
str = [printer stringForKey:@"DefaultPageSize" inTable: @"PPD"];
/* FIXME: Need to check for AutoSelect and probably a million other things... */
if (str == nil)
str = @"A4";
DICTSET(printInfoDefaults, str, NSPrintPaperName);
DICTSET(printInfoDefaults,
[NSValue valueWithSize: [NSPrintInfo sizeForPaperName: str]],
NSPrintPaperSize);
/* Set default margins. FIXME: Probably should check ImageableArea */
DICTSET(printInfoDefaults, NSNUMBER(36), NSPrintRightMargin);
DICTSET(printInfoDefaults, NSNUMBER(36), NSPrintLeftMargin);
DICTSET(printInfoDefaults, NSNUMBER(72), NSPrintTopMargin);
DICTSET(printInfoDefaults, NSNUMBER(72), NSPrintBottomMargin);
DICTSET(printInfoDefaults, NSNUMBER(NSPortraitOrientation),
NSPrintOrientation);
//DICTSET(printInfoDefaults, NSNUMBER(NSClipPagination),
// NSPrintHorizontalPagination);
DICTSET(printInfoDefaults, NSNUMBER(NSAutoPagination),
NSPrintVerticalPagination);
DICTSET(printInfoDefaults, NSNUMBER(1), NSPrintHorizontallyCentered);
DICTSET(printInfoDefaults, NSNUMBER(1), NSPrintVerticallyCentered);
return self;
}

View file

@ -29,27 +29,46 @@
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <math.h>
#include <gnustep/gui/config.h>
#include <Foundation/NSString.h>
#include <Foundation/NSDebug.h>
#include <Foundation/NSData.h>
#include <Foundation/NSException.h>
#include <Foundation/NSThread.h>
#include <Foundation/NSFileManager.h>
#include <Foundation/NSValue.h>
#include <AppKit/AppKitExceptions.h>
#include <AppKit/NSAffineTransform.h>
#include <AppKit/NSGraphicsContext.h>
#include <AppKit/NSView.h>
#include <AppKit/NSPrintPanel.h>
#include <AppKit/NSPrintInfo.h>
#include <AppKit/NSPrintOperation.h>
#include <AppKit/PSOperators.h>
#include <gnustep/base/GSLocale.h>
@interface NSGraphicsContext (Printing)
#define NSNUMBER(a) [NSNumber numberWithInt: (a)]
#define NSFNUMBER(a) [NSNumber numberWithFloat: (a)]
+ (NSGraphicsContext*) postscriptContextWithInfo: (NSDictionary*)info;
@end
/* Local pagination variables needed while printing */
typedef struct _page_info_t {
NSRect scaledBounds; /* View's rect scaled by the user specified scale
and page fitting */
NSRect paperBounds; /* Print area of a page in default user space, possibly
rotated if printing Landscape */
NSRect sheetBounds; /* Print are of a page in default user space */
NSSize paperSize; /* Size of the paper */
int xpages, ypages;
int first, last;
double pageScale; /* Scaling determined from page fitting */
double printScale; /* User specified scaling */
double nupScale; /* Scale required to fit nup pages on the sheet */
int nup; /* Number up pages to print on a sheet */
double lastWidth, lastHeight;
NSPrintingOrientation orient;
} page_info_t;
@interface NSPrintOperation (Private)
@ -62,6 +81,13 @@
@end
@interface NSView (NSPrintOperation)
- (void) _displayPageInRect: (NSRect)pageRect
atPlacement: (NSPoint)location
withInfo: (page_info_t)info;
- (void) _endSheet;
@end
// Subclass for the regular printing
@interface GSPrintOperation: NSPrintOperation
{
@ -99,6 +125,21 @@
static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
/**
<unit>
<heading>Class Description</heading>
<p>
NSPrintOperation controls printing of an NSView. When invoked normally
it will (optionally) display a standard print panel (NSPrintPanel), and
based on the information entered by the user here as well as information
about page layout (see NSPageLayout) tells the NSView to print it's
contents. NSPrintOperation works with the NSView to paginate the output
into appropriately sized and oriented pages and finally delivers the result
to the appropriate place, whether it be a printer, and PostScript file,
or another output.
</p>
</unit>
*/
@implementation NSPrintOperation
//
@ -196,6 +237,9 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
//
// Setting the Print Operation
//
/** Returns the NSPrintOperation object that is currently performing
a print operation (if any).
*/
+ (NSPrintOperation *)currentOperation
{
NSMutableDictionary *dict = [[NSThread currentThread] threadDictionary];
@ -203,6 +247,12 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
return (NSPrintOperation*)[dict objectForKey: NSPrintOperationThreadKey];
}
/** Set the current NSPrintOperation to the supplied operation
object. As this is currently implemented, if a NSPrintOperation
is currently running, that operation is lost (along with any
associated context), so be careful to call this only when there is
no current operation.
*/
+ (void)setCurrentOperation:(NSPrintOperation *)operation
{
NSMutableDictionary *dict = [[NSThread currentThread] threadDictionary];
@ -258,6 +308,9 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
//
// Determining the Type of Operation
//
/** Returns YES if the receiver is performing an operation whose output
is EPS format.
*/
- (BOOL)isEPSOperation
{
return NO;
@ -271,6 +324,8 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
//
// Controlling the User Interface
//
/** Returns the NSPrintPanel associated with the receiver.
*/
- (NSPrintPanel *)printPanel
{
if (_printPanel == nil)
@ -279,26 +334,42 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
return _printPanel;
}
/** Returns YES if the reciever display an NSPrintPanel and other information
when running a print operation. */
- (BOOL)showPanels
{
return _showPanels;
}
/** Sets the NSPrintPanel used by the receiver obtaining and displaying
printing information from/to the user.
*/
- (void)setPrintPanel:(NSPrintPanel *)panel
{
ASSIGN(_printPanel, panel);
}
/** Use this to set whether a print panel is displayed during a printing
operation. If set to NO, then the receiver uses information that
was previously set and does not display any status information about the
progress of the printing operation.
*/
- (void)setShowPanels:(BOOL)flag
{
_showPanels = flag;
}
/** Returns the accessory view used by the NSPrintPanel associated with
the receiver.
*/
- (NSView *)accessoryView
{
return _accessoryView;
}
/** Set the accessory view used by the NSPrintPanel associated with the
receiver.
*/
- (void)setAccessoryView:(NSView *)aView
{
ASSIGN(_accessoryView, aView);
@ -307,17 +378,25 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
//
// Managing the drawing Context
//
/** This method is used by the print operation to create a special
graphics context for use while running the print operation.
*/
- (NSGraphicsContext*)createContext
{
[self subclassResponsibility: _cmd];
return nil;
}
/** Returns the graphic contexts used by the print operation.
*/
- (NSGraphicsContext *)context
{
return _context;
}
/** This method is used by the print operation to destroy the special
graphic context used while running the print operation.
*/
- (void)destroyContext
{
[_context destroyContext];
@ -327,16 +406,23 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
//
// Page Information
//
/** Returns the page currently being printing. Returns 0 if no page
is currently being printed
*/
- (int)currentPage
{
return _currentPage;
}
/** Returns the page order of printing.
*/
- (NSPrintingPageOrder)pageOrder
{
return _pageOrder;
}
/** Set the page order used when printing.
*/
- (void)setPageOrder:(NSPrintingPageOrder)order
{
_pageOrder = order;
@ -345,18 +431,26 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
//
// Running a Print Operation
//
/** Called by the print operation and it has finished running a printing
operation.
*/
- (void)cleanUpOperation
{
_currentPage = 0;
[NSPrintOperation setCurrentOperation: nil];
}
/** Called by the print operation to deliver the results of the printing
operation. This might include sending the output to a printer, a file
or a previewing program. Returns YES if the output was delivered
sucessfully.
*/
- (BOOL)deliverResult
{
// FIXME
return YES;
return NO;
}
/* Private method to run the printing operation */
- (BOOL) _runOperation
{
BOOL result;
@ -367,23 +461,53 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
return NO;
result = NO;
if (_pageOrder == NSUnknownPageOrder)
{
if ([[[_printInfo dictionary] objectForKey: NSPrintReversePageOrder]
boolValue] == YES)
_pageOrder = NSDescendingPageOrder;
else
_pageOrder = NSAscendingPageOrder;
}
[NSGraphicsContext setCurrentContext: _context];
NS_DURING
{
[self _print];
result = YES;
[NSGraphicsContext setCurrentContext: oldContext];
}
NS_HANDLER
{
[NSGraphicsContext setCurrentContext: oldContext];
NSRunAlertPanel(@"Error", @"Printing error: %@",
@"OK", NULL, NULL, localException);
}
NS_ENDHANDLER
[NSGraphicsContext setCurrentContext: oldContext];
[self destroyContext];
return result;
}
- (void) _setupPrintInfo
{
BOOL knowsPageRange;
NSRange viewPageRange;
NSMutableDictionary *dict = [_printInfo dictionary];
knowsPageRange = [_view knowsPageRange: &viewPageRange];
if (knowsPageRange == YES)
{
int first = viewPageRange.location;
int last = NSMaxRange(viewPageRange) - 1;
[dict setObject: NSNUMBER(first) forKey: NSPrintFirstPage];
[dict setObject: NSNUMBER(last) forKey: NSPrintLastPage];
}
}
/** Call this message to run the print operation on a view. This includes
(optionally) displaying a print panel and working with the NSView to
paginate and draw the contents of the view.
*/
- (BOOL)runOperation
{
BOOL result;
@ -394,6 +518,7 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
int button;
[panel setAccessoryView: _accessoryView];
[self _setupPrintInfo];
[panel updateFromPrintInfo];
button = [panel runModal];
[panel setAccessoryView: nil];
@ -438,6 +563,8 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
withObject: contextInfo];
}
/** Run a print operation modally with respect to a window.
*/
- (void)runOperationModalForWindow: (NSWindow *)docWindow
delegate: (id)delegate
didRunSelector: (SEL)didRunSelector
@ -457,6 +584,7 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
of _showPanels
*/
[panel setAccessoryView: _accessoryView];
[self _setupPrintInfo];
[panel updateFromPrintInfo];
[panel beginSheetWithPrintInfo: _printInfo
modalForWindow: docWindow
@ -470,11 +598,15 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
//
// Getting the NSPrintInfo Object
//
/** Returns the NSPrintInfo object associated with the receiver.
*/
- (NSPrintInfo *)printInfo
{
return _printInfo;
}
/** Set the NSPrintInfo object associated with the receiver.
*/
- (void)setPrintInfo:(NSPrintInfo *)aPrintInfo
{
if (aPrintInfo == nil)
@ -486,6 +618,8 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
//
// Getting the NSView Object
//
/** Return the view that is the being printed.
*/
- (NSView *)view
{
return _view;
@ -520,11 +654,246 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
return self;
}
static NSSize
scaleSize(NSSize size, double scale)
{
size.height *= scale;
size.width *= scale;
return size;
}
static NSRect
scaleRect(NSRect rect, double scale)
{
return NSMakeRect(NSMinX(rect) * scale,
NSMinY(rect) * scale,
NSWidth(rect) * scale,
NSHeight(rect) * scale);
}
/* Pagination - guess how many pages we need to print. This could be off
by one in both X and Y because of the view's ability to adjust the
width and height of the printRect during printing. Also set up a bunch
of other information needed for printing.
*/
- (void) _printPaginateWithInfo: (page_info_t *)info knowsRange: (BOOL)knowsRange
{
NSMutableDictionary *dict;
dict = [_printInfo dictionary];
info->paperSize = [_printInfo paperSize];
info->orient = [_printInfo orientation];
info->printScale = [[dict objectForKey: NSPrintScalingFactor] doubleValue];
info->nup = [[dict objectForKey: NSPrintPagesPerSheet] intValue];
info->nupScale = 1;
if (info->nup < 1 || (info->nup > 1 && (((info->nup) & 0x1) == 1)))
{
/* Bad nup value */
info->nup = 1;
[dict setObject: NSNUMBER(1) forKey: NSPrintPagesPerSheet];
}
/* Subtract the margins from the paper size to get print boundary */
info->paperBounds.size = info->paperSize;
info->paperBounds.origin.x = [_printInfo leftMargin];
info->paperBounds.origin.y = [_printInfo bottomMargin];
info->paperBounds.size.width -=
([_printInfo rightMargin]+[_printInfo leftMargin]);
info->paperBounds.size.height -=
([_printInfo topMargin]+[_printInfo bottomMargin]);
info->sheetBounds = info->paperBounds;
if (info->orient == NSLandscapeOrientation)
{
/* Bounding box needs to be in default user space, but the bbox
we get is rotated */
info->sheetBounds = NSMakeRect(NSMinY(info->paperBounds),
NSMinX(info->paperBounds),
NSHeight(info->paperBounds),
NSWidth(info->paperBounds));
}
/* Save this for the view to look at */
[dict setObject: [NSValue valueWithRect: info->paperBounds]
forKey: @"NSPrintPaperBounds"];
[dict setObject: [NSValue valueWithRect: info->sheetBounds]
forKey: @"NSPrintSheetBounds"];
/* Scale bounds by the user specified scaling */
info->scaledBounds = scaleRect(_rect, info->printScale);
if (knowsRange == NO)
{
/* Now calculate page fitting to get page scale */
info->pageScale = 1;
if ([_printInfo horizontalPagination] == NSFitPagination)
info->pageScale = info->paperBounds.size.width
/ NSWidth(info->scaledBounds);
if ([_printInfo verticalPagination] == NSFitPagination)
info->pageScale = MIN(info->pageScale,
NSHeight(info->paperBounds)/NSHeight(info->scaledBounds));
/* Scale bounds by pageScale */
info->scaledBounds = scaleRect(info->scaledBounds, info->pageScale);
/* Now find out how many pages */
info->xpages = ceil(NSWidth(info->scaledBounds)/NSWidth(info->paperBounds));
info->ypages = ceil(NSHeight(info->scaledBounds)/NSHeight(info->paperBounds));
if ([_printInfo horizontalPagination] == NSClipPagination)
info->xpages = 1;
if ([_printInfo verticalPagination] == NSClipPagination)
info->ypages = 1;
}
/* Calculate nup. If nup is an odd multiple of two, secretly change the
page orientation to it's complement to make pages fit better.
*/
if (((int)(info->nup / 2) & 0x1) == 1)
{
float tmp;
if (info->orient == NSLandscapeOrientation)
info->nupScale =
info->paperSize.width/(2*info->paperSize.height);
else
info->nupScale =
info->paperSize.height/(2*info->paperSize.width);
info->nupScale /= (info->nup / 2);
info->orient = (info->orient == NSPortraitOrientation) ?
NSLandscapeOrientation : NSPortraitOrientation;
tmp = info->paperSize.width;
info->paperSize.width = info->paperSize.height;
info->paperSize.height = tmp;
[dict setObject: NSNUMBER(info->orient) forKey: NSPrintOrientation];
}
else if (info->nup > 1)
{
info->nupScale = 2.0 / (float)info->nup;
}
}
/* Our personnel method to calculate the print rect for the specified page.
Note, we assume this function is called in order from our first to last
page. The returned pageRect is in the view's coordinate system
*/
- (NSRect) _rectForPage: (int)page info: (page_info_t *)info
{
int xpage, ypage;
NSRect pageRect;
xpage = (page - 1) % info->xpages;
ypage = (page - 1) % info->ypages;
if (xpage == 0)
info->lastWidth = 0;
if (ypage == 0)
info->lastHeight = 0;
pageRect = NSMakeRect(info->lastWidth, info->lastHeight,
NSWidth(info->paperBounds), NSHeight(info->paperBounds));
pageRect = NSIntersectionRect(pageRect, info->scaledBounds);
/* Scale to view's coordinate system */
return scaleRect(pageRect, 1/(info->pageScale*info->printScale));
}
/* Let the view adjust the page rect we calculated. See assumptions for
_rectForPage:
*/
- (NSRect) _adjustPagesFirst: (int)first
last: (int)last
info: (page_info_t *)info
{
int i;
double hlimit, wlimit;
NSRect pageRect;
hlimit = [_view heightAdjustLimit];
wlimit = [_view widthAdjustLimit];
for (i = first; i <= last; i++)
{
float newVal, limitVal;
pageRect = [self _rectForPage: i info: info];
limitVal = NSMaxY(pageRect) - hlimit * NSHeight(pageRect);
[_view adjustPageHeightNew: &newVal
top: NSMinY(pageRect)
bottom: NSMaxY(pageRect)
limit: limitVal];
if (newVal < NSMaxY(pageRect))
pageRect.size.height = MAX(newVal, limitVal) - NSMinY(pageRect);
limitVal = NSMaxX(pageRect) - wlimit * NSWidth(pageRect);
[_view adjustPageWidthNew: &newVal
left: NSMinX(pageRect)
right: NSMaxX(pageRect)
limit: limitVal];
if (newVal < NSMaxX(pageRect))
pageRect.size.width = MAX(newVal, limitVal) - NSMinX(pageRect);
info->lastWidth = NSMaxX(pageRect)*(info->pageScale*info->printScale);
info->lastHeight = NSMaxY(pageRect)*(info->pageScale*info->printScale);
}
return pageRect;
}
- (void) _print
{
BOOL knowsPageRange;
int i, dir;
BOOL knowsPageRange, allPages;
NSRange viewPageRange;
NSString *clocale;
NSMutableDictionary *dict;
page_info_t info;
dict = [_printInfo dictionary];
/* Setup pagination */
allPages = [[dict objectForKey: NSPrintAllPages] boolValue];
knowsPageRange = [_view knowsPageRange: &viewPageRange];
[self _printPaginateWithInfo: &info knowsRange: knowsPageRange];
if (knowsPageRange == NO)
{
viewPageRange = NSMakeRange(1, (info.xpages * info.ypages));
}
[dict setObject: NSNUMBER(NSMaxRange(viewPageRange) )
forKey: @"NSPrintTotalPages"];
if (allPages == YES)
{
info.first = viewPageRange.location;
info.last = NSMaxRange(viewPageRange) - 1;
}
else
{
info.first = [[dict objectForKey: NSPrintFirstPage] intValue];
info.last = [[dict objectForKey: NSPrintLastPage] intValue];
info.first = MAX(info.first, viewPageRange.location);
info.first = MIN(info.first, NSMaxRange(viewPageRange) - 1);
info.last = MAX(info.last, info.first);
info.last = MIN(info.last, NSMaxRange(viewPageRange) - 1);
viewPageRange = NSMakeRange(info.first, (info.last-info.first)+1);
}
info.lastWidth = info.lastHeight = 0;
[dict setObject: NSFNUMBER(info.nupScale) forKey: @"NSNupScale"];
[dict setObject: NSNUMBER(info.first) forKey: NSPrintFirstPage];
if (allPages == YES && knowsPageRange == NO)
[dict setObject: NSNUMBER(info.first-1) forKey: NSPrintLastPage];
else
[dict setObject: NSNUMBER(info.last) forKey: NSPrintLastPage];
NSDebugLLog(@"NSPrinting", @"Printing pages %d to %d",
info.first, info.last);
NSDebugLLog(@"NSPrinting", @"Printing rect %@, scaled %@",
NSStringFromRect(_rect),
NSStringFromRect(info.scaledBounds));
_currentPage = info.first;
dir = 1;
if (_pageOrder == NSDescendingPageOrder)
{
_currentPage = info.last;
dir = -1;
}
if (dir > 0 && _currentPage != 1)
{
/* Calculate page rects we aren't processing to catch up to the
first page we are */
NSRect pageRect;
pageRect = [self _adjustPagesFirst: 1
last: _currentPage-1
info: &info];
}
/* Reset the current locale to a generic C locale so numbers
get printed correctly for PostScript (maybe we should only
set the numeric locale?). Save the current locale for later. */
@ -534,18 +903,180 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
/* Print the header information */
[_view beginDocument];
/* Setup pagination */
knowsPageRange = [_view knowsPageRange: &viewPageRange];
/* Print each page */
i = 0;
while (i < (info.last-info.first+1))
{
NSPoint location;
NSRect pageRect, scaledPageRect;
if (knowsPageRange == YES)
{
pageRect = [_view rectForPage: _currentPage];
}
else
{
if (dir < 0)
pageRect = [self _adjustPagesFirst: 1
last: _currentPage
info: &info];
else
pageRect = [self _adjustPagesFirst: _currentPage
last: _currentPage
info: &info];
}
NSDebugLLog(@"NSPrinting", @" current page %d, rect %@",
_currentPage, NSStringFromRect(pageRect));
if (NSIsEmptyRect(pageRect))
break;
[_view beginPageInRect: _rect atPlacement: NSMakePoint(0,0)];
[_view displayRectIgnoringOpacity: _rect];
scaledPageRect = scaleRect(pageRect, info.printScale*info.pageScale);
location = [_view locationOfPrintRect: scaledPageRect];
/* Draw using our special view routine */
[_view _displayPageInRect: pageRect
atPlacement: location
withInfo: info];
if (dir > 0 && _currentPage == info.last && allPages == YES)
{
/* Check if adjust pages forced part of the bounds onto
another page */
if (NSMaxX(pageRect) < NSMaxX(_rect)
&& [_printInfo horizontalPagination] != NSClipPagination)
{
info.xpages++;
}
if (NSMaxY(pageRect) < NSMaxY(_rect)
&& [_printInfo verticalPagination] != NSClipPagination)
{
info.ypages++;
}
viewPageRange = NSMakeRange(1, (info.xpages * info.ypages));
info.last = NSMaxRange(viewPageRange) - 1;
}
i++;
_currentPage += dir;
} /* Print each page */
/* Make sure we end the sheet */
if ( info.nup > 1 && (info.last - info.first) % info.nup != info.nup - 1 )
{
[_view drawSheetBorderWithSize: info.paperBounds.size];
[_view _endSheet];
}
[_view endDocument];
GSSetLocale(clocale);
/* Setup/reset for next time */
[dict setObject: NSNUMBER(info.last) forKey: NSPrintLastPage];
if (((int)(info.nup / 2) & 0x1) == 1)
{
info.orient = (info.orient == NSPortraitOrientation) ?
NSLandscapeOrientation : NSPortraitOrientation;
[dict setObject: NSNUMBER(info.orient) forKey: NSPrintOrientation];
}
}
@end
@implementation NSView (NSPrintOperation)
- (void) _displayPageInRect: (NSRect)pageRect
atPlacement: (NSPoint)location
withInfo: (page_info_t)info
{
int currentPage;
float xoffset, yoffset, scale;
NSString *label;
NSGraphicsContext *ctxt = GSCurrentContext();
NSPrintOperation *printOp = [NSPrintOperation currentOperation];
currentPage = [printOp currentPage];
label = nil;
if (info.nup == 1)
label = [NSString stringWithFormat: @"%d", currentPage];
/* Begin a sheet (i.e. a physical page in Postscript terms). If
nup > 1 then this occurs only once every nup pages */
if ((currentPage - info.first) % info.nup == 0)
{
[self beginPage: floor((currentPage - info.first)/info.nup)+1
label: label
bBox: info.sheetBounds
fonts: nil];
DPSPrintf(ctxt, "/__GSsheetsaveobject save def\n");
if (info.orient == NSLandscapeOrientation)
{
DPSrotate(ctxt, 90);
DPStranslate(ctxt, 0, -info.paperSize.height);
}
/* Also offset by margins */
DPStranslate(ctxt, NSMinX(info.paperBounds), NSMinY(info.paperBounds));
}
/* Begin a logical page */
[self beginPageInRect: pageRect atPlacement: location];
scale = info.pageScale * info.printScale;
if (scale != 1.0)
DPSscale(ctxt, scale, scale);
if ([self isFlipped])
{
NSAffineTransformStruct ats = { 1, 0, 0, -1, 0, 1 };
NSAffineTransform *matrix, *flip;
flip = [NSAffineTransform new];
matrix = [NSAffineTransform new];
[matrix makeIdentityMatrix];
[matrix appendTransform: _boundsMatrix];
/*
* The flipping process must result in a coordinate system that
* exactly overlays the original. To do that, we must translate
* the origin by the height of the view.
*/
[flip setTransformStruct: ats];
flip->matrix.ty = NSHeight(_bounds);
[matrix appendTransform: flip];
[matrix concat];
yoffset = NSHeight(_frame) - NSMaxY(pageRect);
}
else
yoffset = 0 - NSMinY(pageRect);
/* Translate so the rect we're printing is on the page */
xoffset = 0 - NSMinX(pageRect);
DPStranslate(ctxt, xoffset, yoffset);
if ((currentPage - info.first) % info.nup == 0)
[self endPageSetup];
/* Do the actual drawing */
[self displayRectIgnoringOpacity: pageRect];
/* End a logical page */
DPSgrestore(ctxt); // Balance gsave in beginPageInRect:
[self drawPageBorderWithSize:
scaleSize(info.paperBounds.size, info.nupScale)];
[self endPage];
/* End a physical page */
if ( ((currentPage - info.first) % info.nup == info.nup-1) )
{
[self drawSheetBorderWithSize: info.paperBounds.size];
[self _endSheet];
}
}
- (void) _endSheet
{
NSGraphicsContext *ctxt = GSCurrentContext();
NSPrintOperation *printOp = [NSPrintOperation currentOperation];
if ([printOp isEPSOperation] == NO)
DPSPrintf(ctxt, "showpage\n");
DPSPrintf(ctxt, "__GSsheetsaveobject restore\n");
DPSPrintf(ctxt, "%%%%PageTrailer\n");
DPSPrintf(ctxt, "\n");
}
@end
@implementation GSPrintOperation
@ -581,7 +1112,9 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
}
[info setObject: _path forKey: @"NSOutputFile"];
_context = RETAIN([NSGraphicsContext postscriptContextWithInfo: info]);
[info setObject: NSGraphicsContextPSFormat
forKey: NSGraphicsContextRepresentationFormatAttributeName];
_context = RETAIN([NSGraphicsContext graphicsContextWithAttributes: info]);
return _context;
}
@ -642,6 +1175,10 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
clocale = GSSetLocale(nil);
GSSetLocale(@"C");
/* Save this for the view to look at. Seems like there should
be a better way to pass it to beginDocument */
[[_printInfo dictionary] setObject: [NSValue valueWithRect: _rect]
forKey: @"NSPrintSheetBounds"];
[_view beginDocument];
[_view beginPageInRect: _rect atPlacement: NSMakePoint(0,0)];
[_view displayRectIgnoringOpacity: _rect];
@ -650,6 +1187,11 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
GSSetLocale(clocale);
}
- (BOOL)isEPSOperation
{
return YES;
}
- (BOOL)deliverResult
{
if (_data != nil && _path != nil)
@ -663,6 +1205,22 @@ static NSString *NSPrintOperationThreadKey = @"NSPrintOperationThreadKey";
return YES;
}
- (NSGraphicsContext*)createContext
{
NSMutableDictionary *info;
if (_context)
return _context;
info = [_printInfo dictionary];
[info setObject: _path forKey: @"NSOutputFile"];
[info setObject: NSGraphicsContextPSFormat
forKey: NSGraphicsContextRepresentationFormatAttributeName];
_context = RETAIN([NSGraphicsContext graphicsContextWithAttributes: info]);
return _context;
}
@end
@implementation GSPDFPrintOperation

View file

@ -144,7 +144,8 @@ static NSPrintPanel *shared_instance;
/* Setup the layout popup */
control = CONTROL(self, NSPPLayoutButton);
list = [NSArray arrayWithObjects: @"1up", @"2up", @"3up", @"4up", nil];
list = [NSArray arrayWithObjects: @"1 up", @"2 up", @"4 up", @"6 up",
@"8 up", nil];
[control removeAllItems];
for (i = 0; i < [list count]; i++)
{
@ -239,11 +240,15 @@ static NSPrintPanel *shared_instance;
else if (tag == NSPPPreviewButton)
{
_picked = NSPPPreviewButton;
NSRunAlertPanel(@"Sorry", @"Previewing of print file not implemented",
@"OK", NULL, NULL);
/* Don't stop the modal session */
return;
}
else if (tag ==NSFaxButton )
{
_picked = NSFaxButton;
NSRunAlertPanel(@"Warning", @"Fax of print file not implemented",
NSRunAlertPanel(@"Sorry", @"Faxing of print file not implemented",
@"OK", NULL, NULL);
/* Don't stop the modal session */
return;
@ -293,7 +298,7 @@ static NSPrintPanel *shared_instance;
NSString *str;
str = [NSString stringWithFormat: @"%d", _pages.location];
[[fromRangeForm cellAtIndex: 0] setStringValue: str];
str = [NSString stringWithFormat: @"%d", NSMaxRange(_pages)];
str = [NSString stringWithFormat: @"%d", NSMaxRange(_pages)-1];
[[toRangeForm cellAtIndex: 0] setStringValue: str];
}
}
@ -361,7 +366,7 @@ static NSPrintPanel *shared_instance;
dict = [info dictionary];
NSDebugLLog(@"NSPrintPanel",
NSDebugLLog(@"NSPrinting",
@"Update PrintInfo dictionary\n %@ \n --------------", dict);
_pages = NSMakeRange([[dict objectForKey: NSPrintFirstPage] intValue],
[[dict objectForKey: NSPrintLastPage] intValue]);
@ -375,7 +380,7 @@ static NSPrintPanel *shared_instance;
if (layout > 4)
layout = 4;
control = CONTROL(self, NSPPLayoutButton);
[control selectItemAtIndex: layout-1];
[control selectItemAtIndex: (int)(layout/2)];
/* Setup the resolution popup */
control = CONTROL(_optionPanel, NSPPResolutionButton);
@ -508,7 +513,7 @@ static NSPrintPanel *shared_instance;
/* Scale */
control = CONTROL(self, NSPPScaleField);
scale = [control intValue]/100;
scale = [control doubleValue]/100.0;
if (scale <= 0)
scale = .1;
if (scale >= 10)
@ -518,7 +523,9 @@ static NSPrintPanel *shared_instance;
forKey: NSPrintScalingFactor];
/* Layout */
layout = [CONTROL(self, NSPPLayoutButton) indexOfSelectedItem] + 1;
layout = [CONTROL(self, NSPPLayoutButton) indexOfSelectedItem] * 2;
if (layout == 0)
layout = 1;
[dict setObject: NSNUMBER(layout) forKey: NSPrintPagesPerSheet];
/* Resolution */
@ -611,7 +618,7 @@ static NSPrintPanel *shared_instance;
}
[info setJobDisposition: sel];
NSDebugLLog(@"NSPrintPanel",
NSDebugLLog(@"NSPrinting",
@"Final info dictionary ----\n %@ \n --------------", dict);
}

View file

@ -37,6 +37,7 @@
#include <float.h>
#include <Foundation/NSString.h>
#include <Foundation/NSCalendarDate.h>
#include <Foundation/NSCoder.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSThread.h>
@ -46,18 +47,24 @@
#include <Foundation/NSValue.h>
#include <Foundation/NSData.h>
#include <Foundation/NSDebug.h>
#include <Foundation/NSPathUtilities.h>
#include <Foundation/NSSet.h>
#include <AppKit/NSView.h>
#include <AppKit/NSWindow.h>
#include <AppKit/GSTrackingRect.h>
#include <AppKit/NSGraphics.h>
#include <AppKit/PSOperators.h>
#include <AppKit/GSVersion.h>
#include <AppKit/NSAffineTransform.h>
#include <AppKit/NSScrollView.h>
#include <AppKit/NSDocumentController.h>
#include <AppKit/NSDocument.h>
#include <AppKit/NSClipView.h>
#include <AppKit/NSFont.h>
#include <AppKit/NSGraphics.h>
#include <AppKit/NSPasteboard.h>
#include <AppKit/NSPrintInfo.h>
#include <AppKit/NSPrintOperation.h>
#include <AppKit/NSScrollView.h>
#include <AppKit/NSView.h>
#include <AppKit/NSWindow.h>
#include <AppKit/PSOperators.h>
/* Variable tells this view and subviews that we're printing. Not really
a class variable because we want it visible to subviews also
@ -69,6 +76,11 @@ struct NSWindow_struct
@defs(NSWindow)
};
@interface NSFont (NSViewFonts)
+ (void) resetUsedFonts;
+ (NSSet *) usedFonts;
@end
@implementation NSView
/*
@ -1352,7 +1364,6 @@ GSSetDragTypes(NSView* obj, NSArray *types)
a superview so we get printed correctly */
[self _matrixToWindow];
[_matrixToWindow makeIdentityMatrix];
_visibleRect = _bounds;
}
else
{
@ -1418,11 +1429,7 @@ GSSetDragTypes(NSView* obj, NSArray *types)
if ([_window gState] == 0)
return;
if (viewIsPrinting != nil)
{
_coordinates_valid = NO;
}
else
if (viewIsPrinting == nil)
{
/* Restore our original gstate */
DPSgrestore(ctxt);
@ -2450,16 +2457,10 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
{
NSMutableData *data = [NSMutableData data];
/* Inform ourselves and subviews that we're printing so we adjust
the PostScript accordingly. Perhaps this could be in the thread
dictionary, but that's probably overkill and slow */
viewIsPrinting = self;
[[NSPrintOperation EPSOperationWithView: self
insideRect: aRect
toData: data] runOperation];
viewIsPrinting = nil;
return data;
}
@ -2495,7 +2496,15 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
- (NSString *)printJobTitle
{
return nil;
id doc;
NSString *title;
doc = [[NSDocumentController sharedDocumentController] documentForWindow:
[self window]];
if (doc)
title = [doc displayName];
else
title = [[self window] title];
return title;
}
/*
@ -2624,8 +2633,31 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
- (NSPoint) locationOfPrintRect: (NSRect)aRect
{
// FIXME: Should depend on the print info
return NSZeroPoint;
int pages;
NSPoint location;
NSRect bounds;
NSMutableDictionary *dict;
NSPrintOperation *printOp = [NSPrintOperation currentOperation];
NSPrintInfo *printInfo = [printOp printInfo];
dict = [printInfo dictionary];
pages = [[dict objectForKey: @"NSPrintTotalPages"] intValue];
if ([dict objectForKey: @"NSPrintPaperBounds"])
bounds = [[dict objectForKey: @"NSPrintPaperBounds"] rectValue];
else
bounds = aRect;
location = NSMakePoint(0, NSHeight(bounds)-NSHeight(aRect));
/* FIXME: I can't figure out how the location for a multi-page document
is computed. Just ignore centering? */
if (pages == 1)
{
if ([printInfo isHorizontallyCentered])
location.x = (NSWidth(bounds) - NSWidth(aRect))/2;
if ([printInfo isVerticallyCentered])
location.y = (NSHeight(bounds) - NSHeight(aRect))/2;
}
return location;
}
- (NSRect) rectForPage: (int)page
@ -2646,13 +2678,26 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
bBox: (NSRect)pageRect
fonts: (NSString*)fontNames
{
NSGraphicsContext *ctxt = GSCurrentContext();
if (aString == nil)
aString = [[NSNumber numberWithInt: ordinalNum] description];
DPSPrintf(ctxt, "%%%%Page: %s %d\n", [aString cString], ordinalNum);
if (NSIsEmptyRect(pageRect) == NO)
DPSPrintf(ctxt, "%%%%PageBoundingBox: %d %d %d %d\n",
(int)NSMinX(pageRect), (int)NSMinY(pageRect),
(int)NSMaxX(pageRect), (int)NSMaxY(pageRect));
if (fontNames)
DPSPrintf(ctxt, "%%%%PageFonts: %s\n", [fontNames cString]);
DPSPrintf(ctxt, "%%%%BeginPageSetup\n");
}
- (void) beginPageSetupRect: (NSRect)aRect placement: (NSPoint)location
{
[self beginPageInRect: aRect atPlacement: location];
}
- (void) beginPrologueBBox: (NSRect)boundingBox
- (void) beginPrologueBBox: (NSRect)bBox
creationDate: (NSString*)dateCreated
createdBy: (NSString*)anApplication
fonts: (NSString*)fontNames
@ -2660,6 +2705,57 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
pages: (int)numPages
title: (NSString*)aTitle
{
NSGraphicsContext *ctxt = GSCurrentContext();
NSPrintOperation *printOp = [NSPrintOperation currentOperation];
NSPrintingOrientation orient;
BOOL epsOp;
epsOp = [printOp isEPSOperation];
orient = [[printOp printInfo] orientation];
if (epsOp)
DPSPrintf(ctxt, "%%!PS-Adobe-3.0 EPSF-3.0\n");
else
DPSPrintf(ctxt, "%%!PS-Adobe-3.0\n");
DPSPrintf(ctxt, "%%%%Title: %s\n", [aTitle cString]);
DPSPrintf(ctxt, "%%%%Creator: %s\n", [anApplication cString]);
DPSPrintf(ctxt, "%%%%CreationDate: %s\n",
[[dateCreated description] cString]);
DPSPrintf(ctxt, "%%%%For: %s\n", [user cString]);
if (fontNames)
DPSPrintf(ctxt, "%%%%DocumentFonts: %s\n", [fontNames cString]);
else
DPSPrintf(ctxt, "%%%%DocumentFonts: (atend)\n");
if (NSIsEmptyRect(bBox) == NO)
DPSPrintf(ctxt, "%%%%BoundingBox: %d %d %d %d\n",
(int)NSMinX(bBox), (int)NSMinY(bBox),
(int)NSMaxX(bBox), (int)NSMaxY(bBox));
else
DPSPrintf(ctxt, "%%%%BoundingBox: (atend)\n");
if (epsOp == NO)
{
if (numPages)
DPSPrintf(ctxt, "%%%%Pages: %d\n", numPages);
else
DPSPrintf(ctxt, "%%%%Pages: (atend)\n");
if ([printOp pageOrder] == NSDescendingPageOrder)
DPSPrintf(ctxt, "%%%%PageOrder: Descend\n");
else if ([printOp pageOrder] == NSAscendingPageOrder)
DPSPrintf(ctxt, "%%%%PageOrder: Ascend\n");
else if ([printOp pageOrder] == NSSpecialPageOrder)
DPSPrintf(ctxt, "%%%%PageOrder: Special\n");
if (orient == NSPortraitOrientation)
DPSPrintf(ctxt, "%%%%Orientation: Portrait\n");
else
DPSPrintf(ctxt, "%%%%Orientation: Landscape\n");
}
DPSPrintf(ctxt, "%%%%GNUstepVersion: %d.%d.%d\n",
GNUSTEP_GUI_MAJOR_VERSION, GNUSTEP_GUI_MINOR_VERSION,
GNUSTEP_GUI_SUBMINOR_VERSION);
}
- (void) addToPageSetup
@ -2668,10 +2764,14 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
- (void) beginSetup
{
NSGraphicsContext *ctxt = GSCurrentContext();
DPSPrintf(ctxt, "%%%%BeginSetup\n");
}
- (void) beginTrailer
{
NSGraphicsContext *ctxt = GSCurrentContext();
DPSPrintf(ctxt, "%%%%Trailer\n");
}
- (void) drawPageBorderWithSize: (NSSize)borderSize
@ -2684,39 +2784,203 @@ static NSView* findByTag(NSView *view, int aTag, unsigned *level)
- (void) endHeaderComments
{
NSGraphicsContext *ctxt = GSCurrentContext();
DPSPrintf(ctxt, "%%%%EndComments\n\n");
}
- (void) endPrologue
{
NSGraphicsContext *ctxt = GSCurrentContext();
DPSPrintf(ctxt, "%%%%EndProlog\n\n");
}
- (void) endSetup
{
NSGraphicsContext *ctxt = GSCurrentContext();
DPSPrintf(ctxt, "%%%%EndSetup\n\n");
}
- (void) endPageSetup
{
NSGraphicsContext *ctxt = GSCurrentContext();
DPSPrintf(ctxt, "%%%%EndPageSetup\n");
}
- (void) endPage
{
int nup;
NSGraphicsContext *ctxt = GSCurrentContext();
NSPrintOperation *printOp = [NSPrintOperation currentOperation];
NSDictionary *dict = [[printOp printInfo] dictionary];
nup = [[dict objectForKey: NSPrintPagesPerSheet] intValue];
if (nup > 1)
{
DPSPrintf(ctxt, "__GSpagesaveobject restore\n\n");
}
}
- (void) endTrailer
{
NSGraphicsContext *ctxt = GSCurrentContext();
DPSPrintf(ctxt, "%%%%EOF\n");
}
/**
Writes header and job information for the PostScript document. This
includes at a minimum, PostScript header information. It may also
include job setup information if the output is intended for a printer
(i.e. not an EPS file). Most of the information for writing the
header comes from the NSPrintOperation and NSPrintInfo objects
associated with the current print operation.
There isn't normally anything that the program needs to override
at the beginning of a document, although if there is additional
setup that needs to be done, you can override the NSView's methods
endHeaderComments, endPrologue, beginSetup, and/or endSetup.
This method calls the above methods in the listed order before
or after writing the required information. For an EPS operation, the
beginSetup and endSetup methods aren't used. */
- (void)beginDocument
{
int first, last, pages, nup;
NSRect bbox;
NSDictionary *dict;
NSGraphicsContext *ctxt = GSCurrentContext();
NSPrintOperation *printOp = [NSPrintOperation currentOperation];
dict = [[printOp printInfo] dictionary];
if (printOp == nil)
{
NSLog(@"[NSView -beginDocument] called without a current print op");
return;
}
/* Inform ourselves and subviews that we're printing so we adjust
the PostScript accordingly. Perhaps this could be in the thread
dictionary, but that's probably overkill and slow */
viewIsPrinting = self;
/* Get pagination information */
nup = [[dict objectForKey: NSPrintPagesPerSheet] intValue];
bbox = NSZeroRect;
if ([dict objectForKey: @"NSPrintSheetBounds"])
bbox = [[dict objectForKey: @"NSPrintSheetBounds"] rectValue];
first = [[dict objectForKey: NSPrintFirstPage] intValue];
last = [[dict objectForKey: NSPrintLastPage] intValue];
pages = last - first + 1;
if (nup > 1)
pages = ceil((float)pages / nup);
/* Begin document structure */
[self beginPrologueBBox: bbox
creationDate: [[NSCalendarDate calendarDate] description]
createdBy: [[NSProcessInfo processInfo] processName]
fonts: nil
forWhom: NSUserName()
pages: pages
title: [self printJobTitle]];
[self endHeaderComments];
DPSPrintf(ctxt, "%%%%BeginProlog\n");
// Prolog goes here !
[self endPrologue];
if ([printOp isEPSOperation] == NO)
{
[self beginSetup];
// Setup goes here !
[self endSetup];
}
[NSFont resetUsedFonts];
/* Make sure we set the visible rect so everything is printed. */
[self _rebuildCoordinates];
_visibleRect = _bounds;
}
- (void)beginPageInRect:(NSRect)aRect
atPlacement:(NSPoint)location
{
int nup;
float scale;
NSRect bounds;
NSGraphicsContext *ctxt = GSCurrentContext();
NSPrintOperation *printOp = [NSPrintOperation currentOperation];
NSDictionary *dict = [[printOp printInfo] dictionary];
if ([dict objectForKey: @"NSPrintPaperBounds"])
bounds = [[dict objectForKey: @"NSPrintPaperBounds"] rectValue];
else
bounds = aRect;
nup = [[dict objectForKey: NSPrintPagesPerSheet] intValue];
if (nup > 1)
{
int page;
float xoff, yoff;
DPSPrintf(ctxt, "/__GSpagesaveobject save def\n");
page = [printOp currentPage]
- [[dict objectForKey: NSPrintFirstPage] intValue];
page = page % nup;
scale = [[dict objectForKey: @"NSNupScale"] floatValue];
if (nup == 2)
xoff = page;
else
xoff = (page % (nup/2));
xoff *= NSWidth(bounds) * scale;
if (nup == 2)
yoff = 0;
else
yoff = (int)((nup-page-1) / (nup/2));
yoff *= NSHeight(bounds) * scale;
DPStranslate(ctxt, xoff, yoff);
DPSgsave(ctxt);
DPSscale(ctxt, scale, scale);
}
else
DPSgsave(ctxt);
/* Translate to placement */
if (location.x != 0 || location.y != 0)
DPStranslate(ctxt, location.x, location.y);
}
- (void)endDocument
{
int first, last, current, pages;
NSSet *fontNames;
NSGraphicsContext *ctxt = GSCurrentContext();
NSPrintOperation *printOp = [NSPrintOperation currentOperation];
NSDictionary *dict = [[printOp printInfo] dictionary];
first = [[dict objectForKey: NSPrintFirstPage] intValue];
last = [[dict objectForKey: NSPrintLastPage] intValue];
pages = last - first + 1;
[self beginTrailer];
if (pages == 0)
{
int nup = [[dict objectForKey: NSPrintPagesPerSheet] intValue];
current = [printOp currentPage];
pages = current - first; // Current is 1 more than the last page
if (nup > 1)
pages = ceil((float)pages / nup);
DPSPrintf(ctxt, "%%%%Pages: %d\n", pages);
}
fontNames = [NSFont usedFonts];
if (fontNames && [fontNames count])
{
NSString *name;
NSEnumerator *e = [fontNames objectEnumerator];
DPSPrintf(ctxt, "%%%%DocumentFonts: %@\n", [e nextObject]);
while ((name = [e nextObject]))
{
DPSPrintf(ctxt, "%%%%+ %@\n", name);
}
}
[self endTrailer];
[self _invalidateCoordinates];
viewIsPrinting = nil;
}
/*

View file

@ -158,6 +158,21 @@ NSString *NSDrawerWillOpenNotification =
NSString *_NSFormCellDidChangeTitleWidthNotification
= @"_NSFormCellDidChangeTitleWidthNotification";
// NSGraphicContext constants
NSString *NSGraphicsContextDestinationAttributeName =
@"NSGraphicsContextDestinationAttributeName";
NSString *NSGraphicsContextPDFFormat =
@"NSGraphicsContextPDFFormat";
NSString *NSGraphicsContextPSFormat =
@"NSGraphicsContextPSFormat";
NSString *NSGraphicsContextRepresentationFormatAttributeName =
@"NSGraphicsContextRepresentationFormatAttributeName";
NSString *NSImageInterpolationDefault = @"NSImageInterpolationDefault";
NSString *NSImageInterpolationNone = @"NSImageInterpolationNone";
NSString *NSImageInterpolationLow = @"NSImageInterpolationLow";
NSString *NSImageInterpolationHigh = @"NSImageInterpolationHigh";
// NSHelpManager notifications;
NSString *NSContextHelpModeDidActivateNotification =
@"NSContextHelpModeDidActivateNotification";