mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-06-01 00:00:48 +00:00
2005-01-25 00:29 Alexander Malmberg <alexander@malmberg.org>
* Headers/AppKit/NSImage.h (-drawAtPoint:fromRect:fraction:) (-drawInRect:fromRect:operation:fraction:): Document. * Source/NSImage.m -drawAtPoint:fromRect:fraction:) (-drawInRect:fromRect:operation:fraction:): Implement. (min, max): New functions. (-drawRepresentation:inRect:): Save the gstate before drawing and restore it afterwards. Fixes bug #11712. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@20611 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
b8834cbfeb
commit
75f09619e9
3 changed files with 235 additions and 11 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
||||||
|
2005-01-25 00:29 Alexander Malmberg <alexander@malmberg.org>
|
||||||
|
|
||||||
|
* Headers/AppKit/NSImage.h (-drawAtPoint:fromRect:fraction:)
|
||||||
|
(-drawInRect:fromRect:operation:fraction:): Document.
|
||||||
|
* Source/NSImage.m -drawAtPoint:fromRect:fraction:)
|
||||||
|
(-drawInRect:fromRect:operation:fraction:): Implement.
|
||||||
|
(min, max): New functions.
|
||||||
|
(-drawRepresentation:inRect:): Save the gstate before drawing
|
||||||
|
and restore it afterwards.
|
||||||
|
|
||||||
|
Fixes bug #11712.
|
||||||
|
|
||||||
2005-01-24 16:57 Alexander Malmberg <alexander@malmberg.org>
|
2005-01-24 16:57 Alexander Malmberg <alexander@malmberg.org>
|
||||||
|
|
||||||
* Source/NSPopUpButtonCell.m (-synchronizeTitleAndSelectedItem): For
|
* Source/NSPopUpButtonCell.m (-synchronizeTitleAndSelectedItem): For
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
Load, manipulate and display images
|
Load, manipulate and display images
|
||||||
|
|
||||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
Copyright (C) 1996, 2005 Free Software Foundation, Inc.
|
||||||
|
|
||||||
Written by: Adam Fedor <fedor@colorado.edu>
|
Written by: Adam Fedor <fedor@colorado.edu>
|
||||||
Date: Feb 1996
|
Date: Feb 1996
|
||||||
|
@ -178,10 +178,26 @@ typedef enum {
|
||||||
- (BOOL) drawRepresentation: (NSImageRep*)imageRep
|
- (BOOL) drawRepresentation: (NSImageRep*)imageRep
|
||||||
inRect: (NSRect)aRect;
|
inRect: (NSRect)aRect;
|
||||||
#ifndef STRICT_OPENSTEP
|
#ifndef STRICT_OPENSTEP
|
||||||
|
/** Calls -drawAtPoint:fromRect:operation:fraction: with
|
||||||
|
<code>dstRect</code> given by <code>point</code> and the size of
|
||||||
|
<code>srcRect</code>. */
|
||||||
- (void) drawAtPoint: (NSPoint)point
|
- (void) drawAtPoint: (NSPoint)point
|
||||||
fromRect: (NSRect)srcRect
|
fromRect: (NSRect)srcRect
|
||||||
operation: (NSCompositingOperation)op
|
operation: (NSCompositingOperation)op
|
||||||
fraction: (float)delta;
|
fraction: (float)delta;
|
||||||
|
|
||||||
|
/** <p>Takes the part of the receiver given by <code>srcRect</code> and
|
||||||
|
draws it in <code>dstRect</code> in the current coordinate system,
|
||||||
|
transforming the image as necessary.
|
||||||
|
</p><p>
|
||||||
|
The image is drawn as if it was drawn to a cleared window, then
|
||||||
|
dissolved using the fraction <code>delta</code> to another cleared
|
||||||
|
window, and finally composited using <code>op</code> to the
|
||||||
|
destination.
|
||||||
|
</p><p>
|
||||||
|
Note that compositing and dissolving doesn't work on all devices
|
||||||
|
(printers, in particular).
|
||||||
|
</p> */
|
||||||
- (void) drawInRect: (NSRect)dstRect
|
- (void) drawInRect: (NSRect)dstRect
|
||||||
fromRect: (NSRect)srcRect
|
fromRect: (NSRect)srcRect
|
||||||
operation: (NSCompositingOperation)op
|
operation: (NSCompositingOperation)op
|
||||||
|
|
216
Source/NSImage.m
216
Source/NSImage.m
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<abstract>Load, manipulate and display images</abstract>
|
<abstract>Load, manipulate and display images</abstract>
|
||||||
|
|
||||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
Copyright (C) 1996, 2005 Free Software Foundation, Inc.
|
||||||
|
|
||||||
Author: Adam Fedor <fedor@colorado.edu>
|
Author: Adam Fedor <fedor@colorado.edu>
|
||||||
Date: Feb 1996
|
Date: Feb 1996
|
||||||
|
@ -24,6 +24,7 @@
|
||||||
*/
|
*/
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include <Foundation/NSArray.h>
|
#include <Foundation/NSArray.h>
|
||||||
#include <Foundation/NSBundle.h>
|
#include <Foundation/NSBundle.h>
|
||||||
|
@ -36,18 +37,39 @@
|
||||||
#include <Foundation/NSValue.h>
|
#include <Foundation/NSValue.h>
|
||||||
|
|
||||||
#include "AppKit/NSImage.h"
|
#include "AppKit/NSImage.h"
|
||||||
|
|
||||||
#include "AppKit/AppKitExceptions.h"
|
#include "AppKit/AppKitExceptions.h"
|
||||||
|
#include "AppKit/NSAffineTransform.h"
|
||||||
#include "AppKit/NSBitmapImageRep.h"
|
#include "AppKit/NSBitmapImageRep.h"
|
||||||
#include "AppKit/NSCachedImageRep.h"
|
#include "AppKit/NSCachedImageRep.h"
|
||||||
#include "AppKit/NSView.h"
|
|
||||||
#include "AppKit/NSWindow.h"
|
|
||||||
#include "AppKit/NSScreen.h"
|
|
||||||
#include "AppKit/NSColor.h"
|
#include "AppKit/NSColor.h"
|
||||||
#include "AppKit/NSPasteboard.h"
|
#include "AppKit/NSPasteboard.h"
|
||||||
#include "AppKit/NSPrintOperation.h"
|
#include "AppKit/NSPrintOperation.h"
|
||||||
|
#include "AppKit/NSScreen.h"
|
||||||
|
#include "AppKit/NSView.h"
|
||||||
|
#include "AppKit/NSWindow.h"
|
||||||
#include "AppKit/PSOperators.h"
|
#include "AppKit/PSOperators.h"
|
||||||
#include "GNUstepGUI/GSDisplayServer.h"
|
#include "GNUstepGUI/GSDisplayServer.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Helpers. Would be nicer to use the C99 fmin/fmax functions, but that
|
||||||
|
isn't currently possible. */
|
||||||
|
static double min(double x, double y)
|
||||||
|
{
|
||||||
|
if (x > y)
|
||||||
|
return y;
|
||||||
|
else
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
static double max(double x, double y)
|
||||||
|
{
|
||||||
|
if (x < y)
|
||||||
|
return y;
|
||||||
|
else
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOL NSImageForceCaching = NO; /* use on missmatch */
|
BOOL NSImageForceCaching = NO; /* use on missmatch */
|
||||||
|
|
||||||
@implementation NSBundle (NSImageAdditions)
|
@implementation NSBundle (NSImageAdditions)
|
||||||
|
@ -827,6 +849,10 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
|
|
||||||
- (BOOL) drawRepresentation: (NSImageRep *)imageRep inRect: (NSRect)aRect
|
- (BOOL) drawRepresentation: (NSImageRep *)imageRep inRect: (NSRect)aRect
|
||||||
{
|
{
|
||||||
|
BOOL r;
|
||||||
|
|
||||||
|
PSgsave();
|
||||||
|
|
||||||
if (_color != nil)
|
if (_color != nil)
|
||||||
{
|
{
|
||||||
NSRect fillrect = aRect;
|
NSRect fillrect = aRect;
|
||||||
|
@ -841,9 +867,14 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_flags.scalable)
|
if (!_flags.scalable)
|
||||||
return [imageRep drawAtPoint: aRect.origin];
|
r = [imageRep drawAtPoint: aRect.origin];
|
||||||
return [imageRep drawInRect: aRect];
|
else
|
||||||
|
r = [imageRep drawInRect: aRect];
|
||||||
|
|
||||||
|
PSgrestore();
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) drawAtPoint: (NSPoint)point
|
- (void) drawAtPoint: (NSPoint)point
|
||||||
|
@ -851,15 +882,180 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
operation: (NSCompositingOperation)op
|
operation: (NSCompositingOperation)op
|
||||||
fraction: (float)delta
|
fraction: (float)delta
|
||||||
{
|
{
|
||||||
//FIXME We need another PS command for this
|
[self drawInRect: NSMakeRect(point.x, point.y, srcRect.size.width,
|
||||||
|
srcRect.size.height)
|
||||||
|
fromRect: srcRect
|
||||||
|
operation: op
|
||||||
|
fraction: delta];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) drawInRect: (NSRect)dstRect
|
- (void) drawInRect: (NSRect)dstRect
|
||||||
fromRect: (NSRect)srcRect
|
fromRect: (NSRect)srcRect
|
||||||
operation: (NSCompositingOperation)op
|
operation: (NSCompositingOperation)op
|
||||||
fraction: (float)delta
|
fraction: (float)fraction
|
||||||
{
|
{
|
||||||
//FIXME We need another PS command for this
|
NSGraphicsContext *ctxt = GSCurrentContext();
|
||||||
|
NSAffineTransform *transform;
|
||||||
|
|
||||||
|
if (!dstRect.size.width || !dstRect.size.height
|
||||||
|
|| !srcRect.size.width || !srcRect.size.height)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (![ctxt isDrawingToScreen])
|
||||||
|
{
|
||||||
|
/* We can't composite or dissolve if we aren't drawing to a screen,
|
||||||
|
so we'll just draw the right part of the image in the right
|
||||||
|
place. */
|
||||||
|
NSSize s;
|
||||||
|
NSPoint p;
|
||||||
|
double fx, fy;
|
||||||
|
|
||||||
|
s = [self size];
|
||||||
|
|
||||||
|
fx = dstRect.size.width / srcRect.size.width;
|
||||||
|
fy = dstRect.size.height / srcRect.size.height;
|
||||||
|
|
||||||
|
p.x = dstRect.origin.x / fx - srcRect.origin.x;
|
||||||
|
p.y = dstRect.origin.y / fy - srcRect.origin.y;
|
||||||
|
|
||||||
|
DPSgsave(ctxt);
|
||||||
|
DPSrectclip(ctxt, dstRect.origin.x, dstRect.origin.y,
|
||||||
|
dstRect.size.width, dstRect.size.height);
|
||||||
|
DPSscale(ctxt, fx, fy);
|
||||||
|
[self drawRepresentation: [self bestRepresentationForDevice: nil]
|
||||||
|
inRect: NSMakeRect(p.x, p.y, s.width, s.height)];
|
||||||
|
DPSgrestore(ctxt);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Figure out what the effective transform from image space to
|
||||||
|
'window space' is. */
|
||||||
|
transform = [ctxt GSCurrentCTM];
|
||||||
|
|
||||||
|
[transform scaleXBy: dstRect.size.width / srcRect.size.width
|
||||||
|
yBy: dstRect.size.height / srcRect.size.height];
|
||||||
|
|
||||||
|
|
||||||
|
/* If the effective transform is the identity transform and there's
|
||||||
|
no dissolve, we can composite from our cache. */
|
||||||
|
if (fraction == 1.0
|
||||||
|
&& fabs(transform->matrix.m11 - 1.0) < 0.01
|
||||||
|
&& fabs(transform->matrix.m12) < 0.01
|
||||||
|
&& fabs(transform->matrix.m21) < 0.01
|
||||||
|
&& fabs(transform->matrix.m22 - 1.0) < 0.01)
|
||||||
|
{
|
||||||
|
[self compositeToPoint: dstRect.origin
|
||||||
|
fromRect: srcRect
|
||||||
|
operation: op];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We can't composite or dissolve directly from the image reps, so we
|
||||||
|
create a temporary off-screen window large enough to hold the
|
||||||
|
transformed image, draw the image rep there, and composite from there
|
||||||
|
to the destination.
|
||||||
|
|
||||||
|
Optimization: Since we do the entire image at once, we might need a
|
||||||
|
huge buffer. If this starts hurting too much, there are a couple of
|
||||||
|
things we could do to:
|
||||||
|
|
||||||
|
1. Take srcRect into account and only process the parts of the image
|
||||||
|
we really need.
|
||||||
|
2. Take the clipping path into account. Desirable, especially if we're
|
||||||
|
being drawn as lots of small strips in a scrollview. We don't have
|
||||||
|
the clipping path here, though.
|
||||||
|
3. Allocate a permanent but small buffer and process the image
|
||||||
|
piecewise.
|
||||||
|
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
NSCachedImageRep *cache;
|
||||||
|
NSSize s;
|
||||||
|
NSPoint p;
|
||||||
|
double x0, y0, x1, y1, w, h;
|
||||||
|
int gState;
|
||||||
|
|
||||||
|
s = [self size];
|
||||||
|
|
||||||
|
/* Figure out how big we need to make the window that'll hold the
|
||||||
|
transformed image. */
|
||||||
|
p = [transform transformPoint: NSMakePoint(0, s.height)];
|
||||||
|
x0 = x1 = p.x;
|
||||||
|
y0 = y1 = p.y;
|
||||||
|
|
||||||
|
p = [transform transformPoint: NSMakePoint(s.width, 0)];
|
||||||
|
x0 = min(x0, p.x);
|
||||||
|
y0 = min(y0, p.y);
|
||||||
|
x1 = max(x1, p.x);
|
||||||
|
y1 = max(y1, p.y);
|
||||||
|
|
||||||
|
p = [transform transformPoint: NSMakePoint(s.width, s.height)];
|
||||||
|
x0 = min(x0, p.x);
|
||||||
|
y0 = min(y0, p.y);
|
||||||
|
x1 = max(x1, p.x);
|
||||||
|
y1 = max(y1, p.y);
|
||||||
|
|
||||||
|
p = [transform transformPoint: NSMakePoint(0, 0)];
|
||||||
|
x0 = min(x0, p.x);
|
||||||
|
y0 = min(y0, p.y);
|
||||||
|
x1 = max(x1, p.x);
|
||||||
|
y1 = max(y1, p.y);
|
||||||
|
|
||||||
|
x0 = floor(x0);
|
||||||
|
y0 = floor(y0);
|
||||||
|
x1 = ceil(x1);
|
||||||
|
y1 = ceil(y1);
|
||||||
|
|
||||||
|
w = x1 - x0;
|
||||||
|
h = y1 - y0;
|
||||||
|
|
||||||
|
/* This is where we want the origin of image space to be in our
|
||||||
|
window. */
|
||||||
|
p.x -= x0;
|
||||||
|
p.y -= y0;
|
||||||
|
|
||||||
|
cache = [[NSCachedImageRep alloc]
|
||||||
|
initWithSize: NSMakeSize(w, h)
|
||||||
|
depth: [[NSScreen mainScreen] depth]
|
||||||
|
separate: YES
|
||||||
|
alpha: YES];
|
||||||
|
|
||||||
|
[[[cache window] contentView] lockFocus];
|
||||||
|
|
||||||
|
DPScompositerect(ctxt, 0, 0, w, h, NSCompositeClear);
|
||||||
|
|
||||||
|
/* Set up the effective transform. We also save a gState with this
|
||||||
|
transform to make it easier to do the final composite. */
|
||||||
|
transform->matrix.tX = p.x;
|
||||||
|
transform->matrix.tY = p.y;
|
||||||
|
[ctxt GSSetCTM: transform];
|
||||||
|
|
||||||
|
gState = [ctxt GSDefineGState];
|
||||||
|
|
||||||
|
[self drawRepresentation: [self bestRepresentationForDevice: nil]
|
||||||
|
inRect: NSMakeRect(0, 0, s.width, s.height)];
|
||||||
|
|
||||||
|
/* If we're doing a dissolve, use a DestinationIn composite to lower
|
||||||
|
the alpha of the pixels. */
|
||||||
|
if (fraction != 1.0)
|
||||||
|
{
|
||||||
|
DPSsetalpha(ctxt, fraction);
|
||||||
|
DPScompositerect(ctxt, 0, 0, s.width, s.height,
|
||||||
|
NSCompositeDestinationIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[[cache window] contentView] unlockFocus];
|
||||||
|
|
||||||
|
|
||||||
|
DPScomposite(ctxt, srcRect.origin.x, srcRect.origin.y,
|
||||||
|
srcRect.size.width, srcRect.size.height, gState,
|
||||||
|
dstRect.origin.x, dstRect.origin.y, op);
|
||||||
|
|
||||||
|
[ctxt GSUndefineGState: gState];
|
||||||
|
|
||||||
|
DESTROY(cache);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) addRepresentation: (NSImageRep *)imageRep
|
- (void) addRepresentation: (NSImageRep *)imageRep
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue