Merge changes from trunk at revision 24178

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/branches/themes@24179 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2006-12-03 07:26:47 +00:00
parent f92292517e
commit 8611a58783
19 changed files with 980 additions and 150 deletions

100
ChangeLog
View file

@ -1,6 +1,102 @@
2006-11-19 Richard Frith-Macdoanld <rfm@gnu.org>
2006-12-03 Richard Frith-Macdoanld <rfm@gnu.org>
Merge in changes from trunk at revision 24178
2006-11-28 Mark Tracy <tracy454@concentric.net>
Belated update to change log (these went in with svn revision 24140).
* Source/externs.m: Added definitions for NSBitmapImage properties key
strings
* Source/tiff.m: Added implementation of NSTiffIsCodecConfigured(codec)
* Source/ngimage-tiff.h: Added declaration of
NSTiffIsCodecConfigured(codec)
* Source/NSBitmapImageRep+GIF.h: Added declaration of
_GIFRepresentationWithProperties:errorMessage:
* Source/NSBitmapImage+GIF.m: Added implementation of
_GIFRepresentationWithProperties:errorMessage:
and static int gs_gif_output(*file, *buffer, len)
* Source/NSBitmapImage+GIF.m (_initBitmapFromGIF:errorMessage:):
Changed loop to terminate after the first image block
is found. Added parsing of graphic control blocks to support
transparency. If transparency is found, adds an alpha channel.
Saves the color table in _properties.
* Source/NSBitmapImage+PNG.h: Added declaration of
_PNGRepresentationWithProperties:
* Source/NSBitmapImage+PNG.m: Added implementation of
_PNGRepresentationWithProperties:
and static void writer_func(png_struct, data, length)
* Source/NSBitmapImage+PNG.m: (_initBitmapFromPNG:):
Added experimental support for the property NSImageGamma
* Source/NSBitmapImage+JPEG.h: Replaced declaration of
representationUsingType:properties
with declaration of _JPEGRepresentationWithProperties:errorMessage:
and removed category (JPEGWriting)
* Source/NSBitmapImage+JPEG.m: Renamed
representationUsingType:properties as
_JPEGRepresentationWithProperties:errorMessage:
and reworked it significantly to support alpha stripping, error
messages, and NSImageProgressive property. NSImageCompressionFactor
now is 0-255 instead of 100-0 quality factor. Returns a real error
message instead of crashing.
* Source/NSBitmapImage+JPEG.m: (_initBitmapFromJPEG:errorMessage:)
Added support for NSImageProgressive property.
* Headers/AppKit/NSBitmapImageRep.h: Added extern declarations for the
properties key strings. Added declaration for NSMutableDictionary *
_properties. Added NSImageJPEG2000FileType to the NSImageFileType enum.
* Source/NSBitmapImageRep.m: (canCompressUsing:): Changed to use the
new NSTiffIsCodecConfigured(codec) instead of a static list.
* Source/NSBitmapImageRep.m: (getTIFFCompressionTypes:count:):
Changed to use the new NSTiffIsCodecConfigures(codec) instead of a
static list.
* Source/NSBitmapImageRep.m: (_localFromCompressionType:): Changed from
an instance method to a class method.
* Source/NSBitmapImageRep.m: (_CompressionTypeFromLocal:): Changed from
an instance method to a class method.
* Source/NSBitmapImageRep.m: (TIFFRepresentationUsingCompression:factor:):
Changed to use new implementation of _localFromCompressionType:
* Source/NSBitmapImageRep.m: (initFromTIFFImage:number:): Changed to
use new implementation of _CompressionTypeFromLocal: and added support
for NSImageCompressionMethod and NSImageCompressionFactor properties
* Source/NSBitmapImageRep.m: (initWithBitmapDataPlanes:pixelsWide:
pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:
colorSpaceName:bytesPerRow:bitsPerPixel:):
Changed to initialize _properties dictionary
* Source/NSBitmapImageRep.m: (dealloc:): Changed to release _properties
* Source/NSBitmapImageRep.m: (setProperty:withValue:) Implemented
functional code in place of TODO:
* Source/NSBitmapImageRep.m: (valueForProperty:) Implemented functional
code in place of TODO:
* Source/NSBitmapImageRep.m: (representationUsingType:properties:):
Implemented working code in place of TODO: It supports writing PNG,
TIFF, GIF and JPEG, with stubs for BMP and JPEG-2000.
* Source/NSBigmapImageRep.m: (representationOfImageRepsInArray:
usingType:properties:): Incomplete implementation in place of TODO:
2006-11-24 Matt Rice <ratmice@gmail.com>
* Source/NSWindowController.m (_windowDidLoad:): Pass an NSZeroPoint to
cascadeTopLeftFromPoint: on the first call.
2006-11-23 Matt Rice <ratmice@gmail.com>
* Source/NSTableView.m (_trackCellAtColumn:row:withEvent:):
Remove check for column editablity.
2006-11-21 Matt Rice <ratmice@gmail.com>
* Source/NSWindow.m (sendEvent:): Fix dragging for views which accept
dragging with subviews which accept dragging.
2006-11-20 Matt Rice <ratmice@gmail.com>
* Source/NSTextView_actions.m: Change cursor movement implementations
when collapsing a selection.
* Source/NSParagraphStyle.m (-setBaseWritingDirection:): Add comment.
* Source/NSAttributedString: Add and remove characters in the word
break character set.
* KeyBindings/DefaultKeyBindings.dict: Change control-f and control-b
to moveForward: and moveBackward:
* Merged in changes from trunk at revision 24133.
2006-11-19 Richard Frith-Macdoanld <rfm@gnu.org>

View file

@ -32,6 +32,7 @@
#import <GNUstepBase/GSVersionMacros.h>
#include <AppKit/NSImageRep.h>
#include <Foundation/NSDictionary.h>
@class NSArray;
@class NSString;
@ -44,21 +45,37 @@ typedef enum _NSTIFFCompression {
NSTIFFCompressionCCITTFAX3,
NSTIFFCompressionCCITTFAX4,
NSTIFFCompressionLZW,
NSTIFFCompressionOldJPEG,
NSTIFFCompressionJPEG,
NSTIFFCompressionNEXT,
NSTIFFCompressionPackBits,
NSTIFFCompressionOldJPEG
NSTIFFCompressionPackBits
} NSTIFFCompression;
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
// FIXME: This is probably wrong
typedef enum _NSBitmapImageFileType {
NSTIFFFileType = 0,
NSBMPFileType = 1,
NSGIFFileType = 2,
NSJPEGFileType = 3,
NSPNGFileType = 4
NSPNGFileType = 4,
NSJPEG2000FileType = 5 // available in Mac OS X v10.4
} NSBitmapImageFileType;
APPKIT_EXPORT NSString *NSImageCompressionMethod; // NSNumber; only for TIFF files
APPKIT_EXPORT NSString *NSImageCompressionFactor; // NSNumber 0.0 to 255.0; only for JPEG files (GNUstep extension: JPEG-compressed TIFFs too)
APPKIT_EXPORT NSString *NSImageDitherTranparency; // NSNumber boolean; only for writing GIF files
APPKIT_EXPORT NSString *NSImageRGBColorTable; // NSData; only for reading & writing GIF files
APPKIT_EXPORT NSString *NSImageInterlaced; // NSNumber boolean; only for writing PNG files
//APPKIT_EXPORT NSString *NSImageColorSyncProfileData; // Mac OX X only
//APPKIT_EXPORT NSString *GSImageICCProfileData; // if & when color management comes to GNUstep
APPKIT_EXPORT NSString *NSImageFrameCount; // NSNumber integer; only for reading animated GIF files
APPKIT_EXPORT NSString *NSImageCurrentFrame; // NSNumber integer; only for animated GIF files
APPKIT_EXPORT NSString *NSImageCurrentFrameDuration; // NSNumber float; only for reading animated GIF files
APPKIT_EXPORT NSString *NSImageLoopCount; // NSNumber integer; only for reading animated GIF files
APPKIT_EXPORT NSString *NSImageGamma; // NSNumber 0.0 to 1.0; only for reading & writing PNG files
APPKIT_EXPORT NSString *NSImageProgressive; // NSNumber boolean; only for reading & writing JPEG files
//APPKIT_EXPORT NSString *NSImageEXIFData; // No GNUstep support yet; for reading & writing JPEG
#endif
@interface NSBitmapImageRep : NSImageRep
@ -67,8 +84,9 @@ typedef enum _NSBitmapImageFileType {
unsigned int _bytesPerRow;
unsigned int _numColors;
unsigned int _bitsPerPixel;
unsigned short _compression;
unsigned short _compression;
float _comp_factor;
NSMutableDictionary *_properties;
BOOL _isPlanar;
unsigned char **_imagePlanes;
NSMutableData *_imageData;

View file

@ -51,10 +51,10 @@
/* Emacs Control keybindings */
"Control-a" = "moveToBeginningOfLine:";
"Control-b" = "moveLeft:";
"Control-b" = "moveBackward:";
"Control-d" = "deleteForward:";
"Control-e" = "moveToEndOfLine:";
"Control-f" = "moveRight:";
"Control-f" = "moveForward:";
"Control-h" = "deleteBackward:";
/* "Control-l" = "centerSelectionInVisibleArea:"; */
"Control-k" = "deleteToEndOfLine:";

View file

@ -78,7 +78,8 @@ static void cache_init_real(void)
[m formUnionWithCharacterSet: cset];
cset = [NSCharacterSet illegalCharacterSet];
[m formUnionWithCharacterSet: cset];
[m removeCharactersInString: @"-"];
[m addCharactersInString: @"<>"];
[m removeCharactersInString: @"_"];
wordBreakCSet = [m copy];
RELEASE (m);

View file

@ -35,6 +35,8 @@
+ (BOOL) _bitmapIsGIF: (NSData *)imageData;
- (id) _initBitmapFromGIF: (NSData *)imageData
errorMessage: (NSString **)errorMsg;
- (NSData *) _GIFRepresentationWithProperties: (NSDictionary *) properties
errorMessage: (NSString **)errorMsg;
@end

View file

@ -7,6 +7,9 @@
Written by: Stefan Kleine Stegemann <stefan@wms-network.de>
Date: Nov 2003
GIF writing, properties and transparency: Mark Tracy <tracy454@concentric.net>
Date: Nov 2006
This file is part of the GNUstep GUI Library.
This library is free software; you can redistribute it and/or
@ -42,6 +45,7 @@ objective-c headers.
#include <Foundation/NSString.h>
#include <Foundation/NSData.h>
#include <Foundation/NSException.h>
#include <Foundation/NSValue.h>
#include "AppKit/NSGraphics.h"
@ -105,6 +109,15 @@ static void gs_gif_init_input_source(gs_gif_input_src *src, NSData *data)
src->pos = 0;
}
/* Function to write GIF to buffer */
static int gs_gif_output(GifFileType *file, const GifByteType *buffer, int len)
{
if (len <= 0) return 0;
NSMutableData * nsData = file->UserData;
[nsData appendBytes: buffer length: len];
return len;
}
/* -----------------------------------------------------------
The gif loading part of NSBitmapImageRep
@ -143,7 +156,10 @@ static void gs_gif_init_input_source(gs_gif_input_src *src, NSData *data)
{\
*errorMsg = msg; \
}\
NSLog(msg);
else \
{\
NSLog(msg);\
}
#define GIF_CREATE_ERROR(msg) \
SET_ERROR_MSG(msg); \
@ -177,16 +193,21 @@ static void gs_gif_init_input_source(gs_gif_input_src *src, NSData *data)
GifByteType *extension;
GifPixelType *imgBuffer = NULL;
GifPixelType *imgBufferPos; /* a position inside imgBuffer */
unsigned char *rgbBuffer; /* image convertet to rgb */
unsigned char *rgbBuffer; /* image converted to rgb */
unsigned rgbBufferPos;
unsigned rgbBufferSize;
ColorMapObject *colorMap;
GifColorType *color;
unsigned char colorIndex;
unsigned pixelSize, rowSize;
int extCode;
int gifrc; /* required by CALL_CHECKED */
int i, j; /* counters */
int imgHeight = 0, imgWidth = 0, imgRow = 0, imgCol = 0;
BOOL hasAlpha = NO;
unsigned char transparentColor = 0;
int sPP = 3; /* samples per pixel */
unsigned short duration = 0;
/* open the image */
gs_gif_init_input_source(&src, imageData);
@ -216,7 +237,9 @@ static void gs_gif_init_input_source(gs_gif_input_src *src, NSData *data)
memset(imgBuffer, file->SBackGroundColor, file->SHeight * rowSize);
/* read the image */
/* read the image
* this delivers the first image in a multi-image gif
*/
do
{
CALL_CHECKED(DGifGetRecordType(file, &recordType), @"GetRecordType");
@ -267,12 +290,19 @@ static void gs_gif_init_input_source(gs_gif_input_src *src, NSData *data)
case EXTENSION_RECORD_TYPE:
{
/* ignore extensions */
/* transparency support */
CALL_CHECKED(DGifGetExtension(file, &extCode, &extension), @"GetExtension");
if (extCode == GRAPHICS_EXT_FUNC_CODE)
{
hasAlpha = (extension[1] & 0x01);
transparentColor = extension[4];
duration = extension[3];
duration = (duration << 8) + extension[2];
}
while (extension != NULL)
{
CALL_CHECKED(DGifGetExtensionNext(file, &extension), @"GetExtensionNext");
}
}
break;
}
@ -282,11 +312,13 @@ static void gs_gif_init_input_source(gs_gif_input_src *src, NSData *data)
break;
}
}
} while (recordType != TERMINATE_RECORD_TYPE);
} while ((recordType != IMAGE_DESC_RECORD_TYPE)
&& (recordType != TERMINATE_RECORD_TYPE));
/* convert the image to rgb */
rgbBufferSize = file->SHeight * (file->SWidth * sizeof(unsigned char) * 3);
sPP = hasAlpha? 4 : 3;
rgbBufferSize = file->SHeight * (file->SWidth * sizeof(unsigned char) * sPP);
rgbBuffer = NSZoneMalloc([self zone], rgbBufferSize);
if (rgbBuffer == NULL)
{
@ -302,10 +334,13 @@ static void gs_gif_init_input_source(gs_gif_input_src *src, NSData *data)
imgBufferPos = imgBuffer + (i * rowSize);
for (j = 0; j < file->SWidth; j++)
{
color = &colorMap->Colors[*(imgBufferPos + (j * pixelSize))];
colorIndex = *(imgBufferPos + j*pixelSize);
color = &colorMap->Colors[colorIndex];
rgbBuffer[rgbBufferPos++] = color->Red;
rgbBuffer[rgbBufferPos++] = color->Green;
rgbBuffer[rgbBufferPos++] = color->Blue;
if (hasAlpha)
rgbBuffer[rgbBufferPos++] = (transparentColor == colorIndex)? 0 : 255;
}
}
@ -317,16 +352,25 @@ static void gs_gif_init_input_source(gs_gif_input_src *src, NSData *data)
pixelsWide: file->SWidth
pixelsHigh: file->SHeight
bitsPerSample: 8
samplesPerPixel: 3
hasAlpha: NO
samplesPerPixel: sPP
hasAlpha: hasAlpha
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
bytesPerRow: file->SWidth * 3
bitsPerPixel: 8 * 3];
bytesPerRow: file->SWidth * sPP
bitsPerPixel: 8 * sPP];
_imageData = [[NSData alloc] initWithBytesNoCopy: rgbBuffer
length: rgbBufferSize];
[self setProperty: NSImageRGBColorTable
withValue: [NSData dataWithBytes: colorMap->Colors
length: sizeof(GifColorType)*colorMap->ColorCount]];
if (duration > 0)
{
[self setProperty: NSImageCurrentFrameDuration
withValue: [NSNumber numberWithFloat: (100.0 * duration)]];
}
[self setProperty: NSImageCurrentFrame
withValue: [NSNumber numberWithInt: 0]];
/* don't forget to close the gif */
DGifCloseFile(file);
@ -334,6 +378,161 @@ static void gs_gif_init_input_source(gs_gif_input_src *src, NSData *data)
return self;
}
- (NSData *) _GIFRepresentationWithProperties: (NSDictionary *) properties
errorMessage: (NSString **)errorMsg
{
NSMutableData * GIFRep = nil; // our return value
GifFileType * GIFFile = NULL;
GifByteType * rgbPlanes = NULL; // giflib needs planar RGB
GifByteType * redPlane = NULL;
GifByteType * greenPlane = NULL;
GifByteType * bluePlane = NULL;
int width, height;
GifByteType * GIFImage = NULL; // intermediate image storage
GifByteType * GIFImageP = NULL;
int h; // general-purpose loop counter
ColorMapObject * GIFColorMap = NULL;
int colorMapSize = 256;
int status; // return status for giflib calls
NSString * colorSpaceName;
BOOL isRGB, hasAlpha;
unsigned char * bitmapData = NULL;
unsigned char * planes[5]; // MAX_PLANES = 5
NSData * colorTable = NULL; // passed in from properties
NSLog(@"GIF representation is experimental");
width = [self pixelsWide];
height = [self pixelsHigh];
if ( !width || !height )
{
SET_ERROR_MSG(@"GIFRepresentation: image is zero size");
return nil;
}
// Giflib wants planar RGB so convert as necessary
colorSpaceName = [self colorSpaceName];
isRGB = ([colorSpaceName isEqualToString: NSDeviceRGBColorSpace] ||
[colorSpaceName isEqualToString: NSCalibratedRGBColorSpace]);
if ( !isRGB )
{
SET_ERROR_MSG(@"GIFRepresentation: Only RGB is supported at this time.");
return nil;
}
hasAlpha = [self hasAlpha];
if ([self isPlanar])
{
[self getBitmapDataPlanes: planes];
redPlane = planes[0];
greenPlane = planes[1];
bluePlane = planes[2];
}
else // interleaved RGB or RGBA
{
OBJC_MALLOC(rgbPlanes, GifByteType, width*height*3);
if ( !rgbPlanes )
{
SET_ERROR_MSG(@"GIFRepresentation: malloc out of memory.");
return nil;
}
redPlane = rgbPlanes;
greenPlane = redPlane + width*height;
bluePlane = greenPlane + width*height;
bitmapData = [self bitmapData];
for (h = 0; h < width*height; h++)
{
*redPlane++ = *bitmapData++;
*greenPlane++ = *bitmapData++;
*bluePlane++ = *bitmapData++;
if (hasAlpha) bitmapData++; // ignore alpha channel
}
redPlane = rgbPlanes;
greenPlane = redPlane + width*height;
bluePlane = greenPlane + width*height;
}
// If you have a color table, you must be certain that it is GIF format
colorTable = [self valueForProperty: NSImageRGBColorTable]; // nil is OK
colorMapSize = (colorTable)? [colorTable length]/sizeof(GifColorType) : 256;
GIFColorMap = MakeMapObject(colorMapSize, [colorTable bytes]);
if ( !GIFColorMap )
{
SET_ERROR_MSG(@"GIFRepresentation (giflib): MakeMapObject() failed.");
OBJC_FREE(rgbPlanes);
return nil;
}
OBJC_MALLOC(GIFImage, GifByteType, height*width);
if ( !GIFImage )
{
SET_ERROR_MSG(@"GIFRepresentation: malloc out of memory.");
OBJC_FREE(rgbPlanes);
}
status = QuantizeBuffer(width, height, &colorMapSize,
redPlane, greenPlane, bluePlane,
GIFImage, GIFColorMap->Colors);
if (status == GIF_ERROR)
{
OBJC_FREE(GIFImage);
OBJC_FREE(rgbPlanes);
return nil;
}
// QuantizeBuffer returns an optimized colorMapSize,
// but we must round up to nearest power of 2
// otherwise MakeColorMap() fails
for (h = 0; h < 8; h++)
if ((1<<h) >= colorMapSize) break;
colorMapSize = 1<<h;
GIFColorMap->ColorCount = colorMapSize;
GIFColorMap->BitsPerPixel = h;
if ( ![self isPlanar] ) OBJC_FREE(rgbPlanes);
// Write the converted image out to the NSData
GIFRep = [NSMutableData dataWithLength: 0];
if ( !GIFRep )
{
OBJC_FREE(GIFImage);
return nil;
}
GIFFile = EGifOpen(GIFRep, gs_gif_output);
status = EGifPutScreenDesc(GIFFile, width, height, 8, 0, NULL);
if (status == GIF_ERROR)
{
SET_ERROR_MSG(@"GIFRepresentation (giflib): EGifPutScreenDesc() failed.");
OBJC_FREE(GIFImage);
return nil;
}
// note we are not supporting interlaced mode
status = EGifPutImageDesc(GIFFile, 0, 0, width, height, FALSE, GIFColorMap);
if (status == GIF_ERROR)
{
SET_ERROR_MSG(@"GIFRepresentation (giflib): EGifPutImageDesc() failed.");
OBJC_FREE(GIFImage);
return nil;
}
GIFImageP = GIFImage;
for (h = 0; h < height ; h++)
{
status = EGifPutLine(GIFFile, GIFImageP, width);
if (status == GIF_ERROR)
{
SET_ERROR_MSG(@"GIFRepresentation (giflib): EGifPutLine() failed.");
OBJC_FREE(GIFImage);
return nil;
}
GIFImageP += width;
}
status = EGifCloseFile(GIFFile);
OBJC_FREE(GIFImage);
return GIFRep;
}
@end
#else /* !HAVE_LIBUNGIF || !HAVE_LIBGIF */
@ -349,6 +548,13 @@ static void gs_gif_init_input_source(gs_gif_input_src *src, NSData *data)
RELEASE(self);
return nil;
}
- (NSData *) _GIFRepresentationWithProperties: (NSDictionary *) properties
errorMessage: (NSString **)errorMsg
{
return nil;
}
@end
#endif /* !HAVE_LIBUNGIF || !HAVE_LIBGIF */

View file

@ -36,7 +36,8 @@
+ (BOOL) _bitmapIsJPEG: (NSData *)imageData;
- (id) _initBitmapFromJPEG: (NSData *)imageData
errorMessage: (NSString **)errorMsg;
- (NSData *) _JPEGRepresentationWithProperties: (NSDictionary *) properties
errorMessage: (NSString **)errorMsg;
@end
#endif // _NSBitmapImageRep_JPEG_H_include

View file

@ -382,6 +382,7 @@ static void gs_jpeg_memory_dest_destroy (j_compress_ptr cinfo)
JDIMENSION sclcount, samplesPerRow, i, j, rowSize;
JSAMPARRAY sclbuffer = NULL;
unsigned char *imgbuffer = NULL;
BOOL isProgressive;
if (!(self = [super init]))
return nil;
@ -417,7 +418,7 @@ static void gs_jpeg_memory_dest_destroy (j_compress_ptr cinfo)
jpeg_read_header(&cinfo, TRUE);
/* we use RGB as target color space */
/* we use RGB as target color space; others are not yet supported */
cinfo.out_color_space = JCS_RGB;
/* decompress */
@ -459,6 +460,8 @@ static void gs_jpeg_memory_dest_destroy (j_compress_ptr cinfo)
}
}
isProgressive = cinfo.progressive_mode;
/* done */
jpeg_finish_decompress(&cinfo);
@ -484,6 +487,9 @@ static void gs_jpeg_memory_dest_destroy (j_compress_ptr cinfo)
bytesPerRow: rowSize
bitsPerPixel: BITS_IN_JSAMPLE * cinfo.output_components];
[self setProperty: NSImageProgressive
withValue: [NSNumber numberWithBool: isProgressive]];
_imageData = [[NSData alloc]
initWithBytesNoCopy: imgbuffer
length: (rowSize * cinfo.output_height)];
@ -491,90 +497,143 @@ static void gs_jpeg_memory_dest_destroy (j_compress_ptr cinfo)
return self;
}
@end
/* -----------------------------------------------------------
The jpeg writing part of NSBitmapImageRep
----------------------------------------------------------- */
@implementation NSBitmapImageRep (JPEGWriting)
- (NSData*) representationUsingType: (NSBitmapImageFileType) storageType
properties: (NSDictionary*) properties
- (NSData*) _JPEGRepresentationWithProperties: (NSDictionary*) properties
errorMessage: (NSString **)errorMsg
{
NSData *ret;
unsigned char *imageSource = [self bitmapData];
int sPP = [self samplesPerPixel];
int width = [self size].width;
int height = [self size].height;
int row_stride = width * sPP;
unsigned char *imageSource;
int sPP;
int width;
int height;
int row_stride;
int quality = 90;
NSNumber *qualityNumber = nil;
NSNumber *progressiveNumber = nil;
NSString *colorSpace = nil;
BOOL isRGB;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
struct gs_jpeg_error_mgr jerrMgr;
JSAMPROW row_pointer[1]; // pointer to a single row
cinfo.err = jpeg_std_error (&jerr);
jpeg_create_compress (&cinfo);
// TODO: handles planar images
if ([self isPlanar])
{
NSLog (@"Planar Image, not handled yet !");
NSString * em = @"JPEG image rep: Planar Image, not handled yet !";
if (errorMsg != NULL)
*errorMsg = em;
else
NSLog (em);
return nil;
}
imageSource = [self bitmapData];
sPP = [self samplesPerPixel];
width = [self size].width;
height = [self size].height;
row_stride = width * sPP;
/* Establish the our custom error handler */
gs_jpeg_error_mgr_init(&jerrMgr);
cinfo.err = jpeg_std_error(&jerrMgr.parent);
jerrMgr.parent.error_exit = gs_jpeg_error_exit;
jerrMgr.parent.output_message = gs_jpeg_output_message;
// establish return context for error handling
if (setjmp(jerrMgr.setjmpBuffer))
{
/* assign the description of possible occured error to errorMsg */
if (errorMsg)
*errorMsg = (jerrMgr.error ? (id)jerrMgr.error : (id)nil);
gs_jpeg_memory_dest_destroy(&cinfo);
jpeg_destroy_compress(&cinfo);
return nil;
}
// initialize libjpeg for compression
jpeg_create_compress (&cinfo);
// specify the destination for the compressed data..
gs_jpeg_memory_dest_create (&cinfo, &ret);
// set parameters
colorSpace = [self colorSpaceName];
isRGB = ([colorSpace isEqualToString: NSDeviceRGBColorSpace]
|| [colorSpace isEqualToString: NSCalibratedRGBColorSpace]);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = sPP;
// note we will strip alpha from RGBA
cinfo.input_components = (isRGB && [self hasAlpha])? 3 : sPP;
cinfo.in_color_space = JCS_UNKNOWN;
if (isRGB) cinfo.in_color_space = JCS_RGB;
if (sPP == 1) cinfo.in_color_space = JCS_GRAYSCALE;
if ([colorSpace isEqualToString: NSDeviceCMYKColorSpace])
cinfo.in_color_space = JCS_CMYK;
if (cinfo.in_color_space == JCS_UNKNOWN)
NSLog(@"JPEG image rep: Using unknown color space with unpredictable results");
// TODO: use the image infos to choose the proper color space
//cinfo.in_color_space = JCS_GRAYSCALE;
colorSpace = [self colorSpaceName];
if ([colorSpace isEqualToString: @"NSCalibratedRGBColorSpace"]
|| [colorSpace isEqualToString: @"NSDeviceRGBColorSpace"])
{
cinfo.in_color_space = JCS_RGB;
}
else
{
NSLog (@"Image Color Space: %@ not handled yet !", colorSpace);
return nil;
}
jpeg_set_defaults (&cinfo);
// set quality
qualityNumber = [properties objectForKey: @"NSImageCompressionFactor"];
qualityNumber = [properties objectForKey: NSImageCompressionFactor];
if (qualityNumber != nil)
{
quality = (int) ([qualityNumber floatValue] * 100);
quality = (int) ((1-[qualityNumber floatValue] / 255.0) * 100.0);
}
// set progressive mode
progressiveNumber = [properties objectForKey: NSImageProgressive];
if (progressiveNumber != nil)
{
cinfo.progressive_mode = [progressiveNumber boolValue];
}
jpeg_set_defaults (&cinfo);
// compress the image
jpeg_set_quality (&cinfo, quality, TRUE);
jpeg_start_compress (&cinfo, TRUE);
while (cinfo.next_scanline < cinfo.image_height)
if (isRGB && [self hasAlpha]) // strip alpha channel before encoding
{
unsigned char * RGB, * pRGB, * pRGBA;
unsigned int iRGB, iRGBA;
OBJC_MALLOC(RGB, unsigned char, 3*width);
while (cinfo.next_scanline < cinfo.image_height)
{
iRGBA = cinfo.next_scanline * row_stride;
pRGBA = &imageSource[iRGBA];
pRGB = RGB;
for (iRGB = 0; iRGB < 3*width; iRGB += 3)
{
memcpy(pRGB, pRGBA, 3);
pRGB +=3;
pRGBA +=4;
}
row_pointer[0] = RGB;
jpeg_write_scanlines (&cinfo, row_pointer, 1);
}
OBJC_FREE(RGB);
}
else // no alpha channel
{
while (cinfo.next_scanline < cinfo.image_height)
{
int index = cinfo.next_scanline * row_stride;
row_pointer[0] = &imageSource[index];
jpeg_write_scanlines (&cinfo, row_pointer, 1);
}
}
jpeg_finish_compress(&cinfo);
@ -601,6 +660,11 @@ static void gs_jpeg_memory_dest_destroy (j_compress_ptr cinfo)
RELEASE(self);
return nil;
}
- (NSData *) _JPEGRepresentationWithProperties: (NSDictionary *) properties
errorMessage: (NSString **)errorMsg
{
return nil;
}
@end
#endif /* !HAVE_LIBJPEG */

View file

@ -34,6 +34,7 @@
@interface NSBitmapImageRep (PNG)
+ (BOOL) _bitmapIsPNG: (NSData *)imageData;
- (id) _initBitmapFromPNG: (NSData *)imageData;
- (NSData *) _PNGRepresentationWithProperties: (NSDictionary *) properties;
@end
#endif

View file

@ -35,8 +35,19 @@
#include <Foundation/NSData.h>
#include <Foundation/NSException.h>
#include <Foundation/NSValue.h>
#include "AppKit/NSGraphics.h"
#if defined(PNG_FLOATING_POINT_SUPPORT)
# define PNG_FLOATING_POINT 1
#else
# define PNG_FLOATING_POINT 0
#endif
#if defined(PNG_gAMA_SUPPORT)
# define PNG_gAMA 1
#else
# define PNG_gAMA 0
#endif
@implementation NSBitmapImageRep (PNG)
@ -212,11 +223,141 @@ static void reader_func(png_structp png_struct, png_bytep data,
initWithBytesNoCopy: buf
length: bytes_per_row * height];
if (PNG_INFO_gAMA & png_info->valid)
{
double file_gamma = 2.2;
if (PNG_FLOATING_POINT)
{
png_get_gAMA(png_struct, png_info, &file_gamma);
// remap file_gamma [1.0, 2.5] to property [0.0, 1.0]
file_gamma = (file_gamma - 1.0)/1.5;
}
else // fixed point
{
png_fixed_point int_gamma = 220000;
png_get_gAMA_fixed(png_struct, png_info, &int_gamma);
// remap gamma [0.0, 1.0] to [100000, 250000]
file_gamma = ((double)int_gamma - 100000.0)/150000.0;
}
[self setProperty: NSImageGamma
withValue: [NSNumber numberWithDouble: file_gamma]];
//NSLog(@"PNG file gamma: %f", file_gamma);
}
png_destroy_read_struct(&png_struct, &png_info, &png_end_info);
return self;
}
/***** PNG writing support ******/
static void writer_func(png_structp png_struct, png_bytep data,
png_size_t length)
{
NSMutableData * PNGRep = png_get_io_ptr(png_struct);
[PNGRep appendBytes: data length: length];
}
- (NSData *) _PNGRepresentationWithProperties: (NSDictionary *) properties
{
png_structp png_struct;
png_infop png_info;
int width, height, depth;
unsigned char * bitmapData;
int bytes_per_row;
NSString * colorspace;
NSMutableData * PNGRep = nil;
int type = -1; // illegal value
int interlace = PNG_INTERLACE_NONE;
int transforms = PNG_TRANSFORM_IDENTITY; // no transformations
NSNumber * gammaNumber = nil;
double gamma = 0.0;
if ([self isPlanar]) // don't handle planar yet
{
return nil;
}
// get the image parameters
width = [self pixelsWide];
height = [self pixelsHigh];
bytes_per_row = [self bytesPerRow];
colorspace = [self colorSpaceName];
depth = [self bitsPerSample];
gammaNumber = [properties objectForKey: NSImageGamma];
gamma = [gammaNumber doubleValue];
if ([[properties objectForKey: NSImageInterlaced] boolValue])
interlace = PNG_INTERLACE_ADAM7;
if ([colorspace isEqualToString: NSCalibratedWhiteColorSpace] ||
[colorspace isEqualToString: NSDeviceWhiteColorSpace])
type = PNG_COLOR_TYPE_GRAY;
if ([colorspace isEqualToString: NSCalibratedRGBColorSpace] ||
[colorspace isEqualToString: NSDeviceRGBColorSpace])
type = PNG_COLOR_TYPE_RGB;
if ([self hasAlpha]) type = type | PNG_COLOR_MASK_ALPHA;
// make the PNG structures
// ignore errors until I write the handlers
png_struct = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_struct)
{
return nil;
}
png_info = png_create_info_struct(png_struct);
if (!png_info)
{
png_destroy_write_struct(&png_struct, NULL);
return nil;
}
if (setjmp(png_jmpbuf(png_struct)))
{
png_destroy_write_struct(&png_struct, &png_info);
return nil;
}
// init structures
PNGRep = [NSMutableData dataWithLength: 0];
png_info_init_3(&png_info, png_sizeof(png_info));
png_set_write_fn(png_struct, PNGRep, writer_func, NULL);
png_set_IHDR(png_struct, png_info, width, height, depth,
type, interlace, PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
if (gammaNumber)
{
NSLog(@"PNGRepresentation: gamma support is experimental");
if (PNG_FLOATING_POINT)
{
// remap gamma [0.0, 1.0] to [1.0, 2.5]
png_set_gAMA(png_struct, png_info, (gamma * 1.5 + 1.0));
}
else // fixed point
{
// remap gamma [0.0, 1.0] to [100000, 250000]
int int_gamma = (int)(gamma * 150000.0 + 100000.0);
png_set_gAMA_fixed(png_struct, png_info, int_gamma);
}
}
// get rgb data and row pointers and
// write PNG out to NSMutableData
bitmapData = [self bitmapData];
{
unsigned char *row_pointers[height];
int i;
for (i = 0 ; i < height ; i++)
row_pointers[i] = bitmapData + i * bytes_per_row;
png_set_rows(png_struct, png_info, row_pointers);
png_write_png(png_struct, png_info, transforms, NULL);
}
NSLog(@"PNG representation is experimental: %i bytes written", [PNGRep length]);
png_destroy_write_struct(&png_struct, &png_info);
return PNGRep;
}
@end
#else /* !HAVE_LIBPNG */
@ -231,6 +372,10 @@ static void reader_func(png_structp png_struct, png_bytep data,
RELEASE(self);
return nil;
}
- (NSData *) _PNGRepresentationWithProperties: (NSDictionary *) properties
{
return nil;
}
@end
#endif /* !HAVE_LIBPNG */

View file

@ -55,19 +55,14 @@
/* Maximum number of planes */
#define MAX_PLANES 5
/* FIXME: By default the libtiff library (v3.5.7 and less at least) do
not support LZW compression, but it's not possible to find out if it
does or not until after we've already written an image :-(. */
static BOOL supports_lzw_compression = NO;
/* Backend methods (optional) */
@interface NSBitmapImageRep (GSPrivate)
// GNUstep extension
- _initFromTIFFImage: (TIFF *)image number: (int)imageNumber;
// Internal
- (int) _localFromCompressionType: (NSTIFFCompression)type;
- (NSTIFFCompression) _compressionTypeFromLocal: (int)type;
+ (int) _localFromCompressionType: (NSTIFFCompression)type;
+ (NSTIFFCompression) _compressionTypeFromLocal: (int)type;
@end
/**
@ -526,6 +521,7 @@ static BOOL supports_lzw_compression = NO;
{
[self setOpaque: YES];
}
_properties = [[NSMutableDictionary alloc] init];
return self;
}
@ -555,6 +551,7 @@ static BOOL supports_lzw_compression = NO;
{
NSZoneFree([self zone],_imagePlanes);
RELEASE(_imageData);
RELEASE(_properties);
[super dealloc];
}
@ -763,7 +760,7 @@ static BOOL supports_lzw_compression = NO;
}
info.extraSamples = (_hasAlpha) ? 1 : 0;
info.compression = [self _localFromCompressionType: type];
info.compression = [NSBitmapImageRep _localFromCompressionType: type];
if (factor < 0)
factor = 0;
if (factor > 255)
@ -790,23 +787,81 @@ static BOOL supports_lzw_compression = NO;
usingType:(NSBitmapImageFileType)storageType
properties:(NSDictionary *)properties
{
// TODO
// Partial implementation only returns data for the first imageRep in the array
// and only works for NSBitmapImageRep or subclasses thereof.
//FIXME: This only outputs one of the ImageReps
NSEnumerator *enumerator = [imageReps objectEnumerator];
NSImageRep *rep;
while ((rep = [enumerator nextObject]) != nil)
{
if ([rep isKindOfClass: self])
{
return [(NSBitmapImageRep*)rep representationUsingType: storageType
properties: properties];
}
}
return nil;
}
- (NSData *)representationUsingType:(NSBitmapImageFileType)storageType
properties:(NSDictionary *)properties
{
// TODO
// if it exists, the passed in properties takes precedence over the internal _properties
NSDictionary * __properties;
__properties = (properties)? properties : (NSDictionary *)_properties;
switch (storageType)
{
case NSTIFFFileType:
{
NSNumber * property;
float factor = _comp_factor;
NSTIFFCompression compression = _compression;
if ((property = [__properties objectForKey: NSImageCompressionMethod]))
compression = [property unsignedShortValue];
if ((property = [__properties objectForKey: NSImageCompressionFactor]))
factor = [property floatValue];
if ([self canBeCompressedUsing: compression] == NO)
{
factor = 0.0;
compression = NSTIFFCompressionNone;
}
return [self TIFFRepresentationUsingCompression: compression factor: factor];
}
case NSBMPFileType:
NSLog(@"BMP representation is not yet implemented");
return nil;
case NSGIFFileType:
return [self _GIFRepresentationWithProperties: __properties
errorMessage: NULL];
case NSJPEGFileType:
return [self _JPEGRepresentationWithProperties: __properties
errorMessage: NULL];
case NSPNGFileType:
return [self _PNGRepresentationWithProperties: __properties];
case NSJPEG2000FileType:
NSLog(@"JPEG2000 representation is not yet implemented");
return nil;
}
return nil;
}
//
// Setting and Checking Compression Types
//
/** Returns a C-array of available TIFF compression types.
*/
+ (void) getTIFFCompressionTypes: (const NSTIFFCompression **)list
count: (int *)numTypes
{
// the GNUstep supported types
static NSTIFFCompression types[] = {
NSTIFFCompressionNone,
NSTIFFCompressionCCITTFAX3,
@ -817,11 +872,22 @@ static BOOL supports_lzw_compression = NO;
NSTIFFCompressionPackBits,
NSTIFFCompressionOldJPEG
};
// check with libtiff to see what is really available
int i, j;
static NSTIFFCompression checkedTypes[8];
for (i = 0, j = 0; i < 8; i++)
{
if (NSTiffIsCodecConfigured([NSBitmapImageRep _localFromCompressionType: types[i]]))
{
checkedTypes[j] = types[i];
j++;
}
}
if (list)
*list = types;
*list = checkedTypes;
if (numTypes)
*numTypes = sizeof(types)/sizeof(*types);
*numTypes = j;
}
+ (NSString*) localizedNameForTIFFCompressionType: (NSTIFFCompression)type
@ -845,30 +911,26 @@ static BOOL supports_lzw_compression = NO;
- (BOOL) canBeCompressedUsing: (NSTIFFCompression)compression
{
BOOL does;
int codecConf =
NSTiffIsCodecConfigured([NSBitmapImageRep _localFromCompressionType: compression]);
switch (compression)
{
case NSTIFFCompressionCCITTFAX3:
case NSTIFFCompressionCCITTFAX4:
if (_numColors == 1 && _bitsPerSample == 1)
if (_numColors == 1 && _bitsPerSample == 1 && codecConf != 0)
does = YES;
else
does = NO;
break;
case NSTIFFCompressionLZW:
does = supports_lzw_compression;
break;
case NSTIFFCompressionNone:
case NSTIFFCompressionJPEG:
case NSTIFFCompressionJPEG: // this is a GNUstep extension; Cocoa does not support
case NSTIFFCompressionPackBits:
case NSTIFFCompressionOldJPEG:
does = YES;
break;
case NSTIFFCompressionNEXT:
default:
does = NO;
does = (codecConf != 0);
}
return does;
}
@ -894,13 +956,19 @@ static BOOL supports_lzw_compression = NO;
- (void)setProperty:(NSString *)property withValue:(id)value
{
// TODO
if (value)
{
[_properties setObject: value forKey: property];
}
else // clear the property
{
[_properties removeObjectForKey: property];
}
}
- (id)valueForProperty:(NSString *)property
{
// TODO
return nil;
return [_properties objectForKey: property];
}
// NSCopying protocol
@ -978,7 +1046,7 @@ static BOOL supports_lzw_compression = NO;
@implementation NSBitmapImageRep (GSPrivate)
- (int) _localFromCompressionType: (NSTIFFCompression)type
+ (int) _localFromCompressionType: (NSTIFFCompression)type
{
switch (type)
{
@ -996,7 +1064,7 @@ static BOOL supports_lzw_compression = NO;
return COMPRESSION_NONE;
}
- (NSTIFFCompression) _compressionTypeFromLocal: (int)type
+ (NSTIFFCompression) _compressionTypeFromLocal: (int)type
{
switch (type)
{
@ -1057,9 +1125,15 @@ static BOOL supports_lzw_compression = NO;
colorSpaceName: space
bytesPerRow: 0
bitsPerPixel: 0];
_compression = [self _compressionTypeFromLocal: info->compression];
_compression = [NSBitmapImageRep _compressionTypeFromLocal: info->compression];
_comp_factor = 255 * (1 - ((float)info->quality)/100.0);
// Note that Cocoa does not do this, even though the docs say it should
[_properties setObject: [NSNumber numberWithUnsignedShort: _compression]
forKey: NSImageCompressionMethod];
[_properties setObject: [NSNumber numberWithFloat: _comp_factor]
forKey: NSImageCompressionFactor];
if (NSTiffRead(image, info, [self bitmapData]))
{
OBJC_FREE(info);

View file

@ -514,6 +514,19 @@ static NSParagraphStyle *defaultStyle = nil;
- (void) setBaseWritingDirection: (NSWritingDirection)direction
{
/*
* FIXME there is some confusion regarding natural writing direction.
*
* this method is documented as setting
* NSWritingDirectionLeftToRight or NSWritingDirectionRightToLeft
* based on the users language preferences.
* when encountering NSWritingDirectionNaturalDirection
*
* NSWritingDirectionNatural constant is documented as using the
* unicode bidi algorithm.
*
* no idea what the constant name or behaviour actually is.
*/
_baseDirection = direction;
}

View file

@ -3398,8 +3398,8 @@ static inline float computePeriod(NSPoint mouseLocationWin,
{
id newValue = [cell objectValue];
if ([tb isEditable]
&& originalValue != newValue
/* don't check editability that only pertains to editColumn:... */
if (originalValue != newValue
&& ![originalValue isEqual: newValue])
{
[self _setObjectValue: newValue

View file

@ -52,6 +52,7 @@
#include "AppKit/NSScrollView.h"
#include "AppKit/NSTextStorage.h"
#include "AppKit/NSTextView.h"
#include "AppKit/NSParagraphStyle.h"
/*
These methods are for user actions, ie. they are normally called from
@ -761,11 +762,11 @@ added to the selection (1,3).
[self scrollRangeToVisible: NSMakeRange(cindex, 0)];
}
- (void) _move: (GSInsertionPointMovementDirection)direction
distance: (float)distance
select: (BOOL)select
- (void) _moveFrom: (unsigned int)cindex
direction: (GSInsertionPointMovementDirection)direction
distance: (float)distance
select: (BOOL)select
{
unsigned int cindex;
int new_direction;
if (direction == GSInsertionPointMoveUp ||
@ -783,7 +784,6 @@ added to the selection (1,3).
new_direction = 0;
}
cindex = [self _movementOrigin];
if (new_direction != _currentInsertionPointMovementDirection ||
!new_direction)
{
@ -801,6 +801,64 @@ added to the selection (1,3).
_currentInsertionPointMovementDirection = new_direction;
}
- (void) _move: (GSInsertionPointMovementDirection)direction
distance: (float)distance
select: (BOOL)select
{
[self _moveFrom: [self _movementOrigin]
direction: direction
distance: distance
select: select];
}
/*
* returns the character index for the left or right side of the selected text
* based upon the writing direction of the paragraph style.
* it should only be used when moving a literal direction such as left right
* up or down, not directions like forward, backward, beginning or end
*/
- (unsigned int) _characterIndexForSelectedRange: (NSRange)range
direction: (GSInsertionPointMovementDirection)direction
{
unsigned int cIndex;
NSParagraphStyle *parStyle;
NSWritingDirection writingDirection;
parStyle = [[self typingAttributes]
objectForKey: NSParagraphStyleAttributeName];
writingDirection = [parStyle baseWritingDirection];
switch (writingDirection)
{
case NSWritingDirectionLeftToRight:
cIndex = (direction == GSInsertionPointMoveLeft
|| direction == GSInsertionPointMoveUp)
? range.location
: NSMaxRange(range);
break;
case NSWritingDirectionRightToLeft:
cIndex = (direction == GSInsertionPointMoveLeft
|| direction == GSInsertionPointMoveUp)
? NSMaxRange(range)
: range.location;
break;
case NSWritingDirectionNaturalDirection:
// not sure if we should see this as it should resolve to either
// LeftToRight or RightToLeft in NSParagraphStyle
// for the users language.
//
// currently falls back to default..
default:
/* default to LeftToRight */
cIndex = (direction == GSInsertionPointMoveLeft
|| direction == GSInsertionPointMoveUp)
? range.location
: NSMaxRange(range);
break;
}
return cIndex;
}
/*
Insertion point movement actions.
@ -811,7 +869,12 @@ check if there was a reason for that.
- (void) moveUp: (id)sender
{
[self _move: GSInsertionPointMoveUp
NSRange range = [self selectedRange];
unsigned int cIndex = [self _characterIndexForSelectedRange:range
direction:GSInsertionPointMoveUp];
[self _moveFrom: cIndex
direction: GSInsertionPointMoveUp
distance: 0.0
select: NO];
}
@ -825,7 +888,11 @@ check if there was a reason for that.
- (void) moveDown: (id)sender
{
[self _move: GSInsertionPointMoveDown
NSRange range = [self selectedRange];
unsigned int cIndex = [self _characterIndexForSelectedRange: range
direction: GSInsertionPointMoveDown];
[self _moveFrom: cIndex
direction: GSInsertionPointMoveDown
distance: 0.0
select: NO];
}
@ -839,26 +906,56 @@ check if there was a reason for that.
- (void) moveLeft: (id)sender
{
[self _move: GSInsertionPointMoveLeft
distance: 0.0
select: NO];
NSRange range = [self selectedRange];
if (range.length)
{
unsigned int cIndex;
cIndex = [self _characterIndexForSelectedRange: range
direction:GSInsertionPointMoveLeft];
[self _moveTo: cIndex select: NO];
}
else
{
[self _move: GSInsertionPointMoveLeft
distance: 0.0
select: NO];
}
}
- (void) moveRight: (id)sender
{
[self _move: GSInsertionPointMoveRight
distance: 0.0
select: NO];
NSRange range = [self selectedRange];
if (range.length)
{
unsigned int cIndex;
cIndex = [self _characterIndexForSelectedRange: range
direction: GSInsertionPointMoveRight];
[self _moveTo: cIndex select: NO];
}
else
{
[self _move: GSInsertionPointMoveRight
distance: 0.0
select: NO];
}
}
- (void) moveBackward: (id)sender
{
unsigned int to = [self _movementOrigin];
NSRange range = [self selectedRange];
unsigned int to = range.location;
if (to == 0)
return;
to--;
if (range.length == 0 && to)
{
to--;
}
[self _moveTo: to
select: NO];
}
@ -876,14 +973,18 @@ check if there was a reason for that.
- (void) moveForward: (id)sender
{
unsigned int to = [self _movementOrigin];
if (to == [_textStorage length])
return;
to++;
NSRange range = [self selectedRange];
unsigned int to = NSMaxRange(range);
if (range.length == 0 && to != [_textStorage length])
{
to++;
}
[self _moveTo: to
select: NO];
}
- (void) moveForwardAndModifySelection: (id)sender
{
unsigned int to = [self _movementOrigin];
@ -897,9 +998,11 @@ check if there was a reason for that.
- (void) moveWordBackward: (id)sender
{
NSRange range = [self selectedRange];
unsigned int newLocation;
newLocation = [_textStorage nextWordFromIndex: [self _movementOrigin]
unsigned int cIndex = range.location;
newLocation = [_textStorage nextWordFromIndex: cIndex
forward: NO];
[self _moveTo: newLocation
select: NO];
@ -918,8 +1021,9 @@ check if there was a reason for that.
- (void) moveWordForward: (id)sender
{
unsigned newLocation;
unsigned int cIndex = NSMaxRange([self selectedRange]);
newLocation = [_textStorage nextWordFromIndex: [self _movementOrigin]
newLocation = [_textStorage nextWordFromIndex: cIndex
forward: YES];
[self _moveTo: newLocation
select: NO];
@ -961,10 +1065,11 @@ check if there was a reason for that.
- (void) moveToBeginningOfParagraph: (id)sender
{
NSRange aRange;
NSRange aRange = [self selectedRange];
aRange = [[_textStorage string] lineRangeForRange:
NSMakeRange([self _movementOrigin], 0)];
NSMakeRange(aRange.location, 0)];
[self _moveTo: aRange.location
select: NO];
}
@ -984,9 +1089,19 @@ check if there was a reason for that.
NSRange aRange;
unsigned newLocation;
unsigned maxRange;
unsigned int cIndex;
if (flag)
{
cIndex = [self _movementOrigin];
}
else
{
cIndex = NSMaxRange([self selectedRange]);
}
aRange = [[_textStorage string] lineRangeForRange:
NSMakeRange([self _movementOrigin], 0)];
NSMakeRange(cIndex, 0)];
maxRange = NSMaxRange (aRange);
if (maxRange == 0)
@ -1047,7 +1162,11 @@ check if there was a reason for that.
and layout is left-to-right */
- (void) moveToBeginningOfLine: (id)sender
{
[self _move: GSInsertionPointMoveLeft
NSRange range = [self selectedRange];
unsigned int cIndex = range.location;
[self _moveFrom: cIndex
direction: GSInsertionPointMoveLeft
distance: 1e8
select: NO];
}
@ -1061,7 +1180,10 @@ and layout is left-to-right */
- (void) moveToEndOfLine: (id)sender
{
[self _move: GSInsertionPointMoveRight
unsigned int cIndex = NSMaxRange([self selectedRange]);
[self _moveFrom: cIndex
direction: GSInsertionPointMoveRight
distance: 1e8
select: NO];
}
@ -1084,6 +1206,17 @@ and layout is left-to-right */
float scrollDelta;
float oldOriginY;
float newOriginY;
unsigned int cIndex;
if (flag)
{
cIndex = [self _movementOrigin];
}
else
{
cIndex = [self _characterIndexForSelectedRange: [self selectedRange]
direction: GSInsertionPointMoveDown];
}
/*
* Scroll; also determine how far to move the insertion point.
@ -1099,7 +1232,8 @@ and layout is left-to-right */
return;
}
[self _move: GSInsertionPointMoveDown
[self _moveFrom: cIndex
direction: GSInsertionPointMoveDown
distance: scrollDelta
select: flag];
}
@ -1125,7 +1259,17 @@ and layout is left-to-right */
float scrollDelta;
float oldOriginY;
float newOriginY;
unsigned int cIndex;
if (flag)
{
cIndex = [self _movementOrigin];
}
else
{
cIndex = [self _characterIndexForSelectedRange:[self selectedRange]
direction: GSInsertionPointMoveUp];
}
/*
* Scroll; also determine how far to move the insertion point.
*/
@ -1140,7 +1284,8 @@ and layout is left-to-right */
return;
}
[self _move: GSInsertionPointMoveUp
[self _moveFrom: cIndex
direction: GSInsertionPointMoveUp
distance: -scrollDelta
select: flag];
}

View file

@ -3596,16 +3596,20 @@ resetCursorRectsForView(NSView *theView)
{
BOOL isEntry;
dragInfo = [GSServerForWindow(self) dragInfo];
v = [_wv hitTest: [theEvent locationInWindow]];
while (v != nil && ((NSViewPtr)v)->_rFlags.has_draginfo == 0)
while (v != nil)
{
if (((NSViewPtr)v)->_rFlags.has_draginfo != 0
&& GSViewAcceptsDrag(v, dragInfo))
break;
v = [v superview];
}
if (v == nil)
{
v = _wv;
}
dragInfo = [GSServerForWindow(self) dragInfo];
if (_lastDragView == v)
{
isEntry = NO;

View file

@ -401,30 +401,16 @@
if ([self shouldCascadeWindows])
{
static NSPoint nextWindowLocation = { 0.0, 0.0 };
static BOOL firstWindow = YES;
if (firstWindow)
{
NSRect windowFrame = [_window frame];
/* Start with the frame as set */
nextWindowLocation = NSMakePoint (NSMinX (windowFrame),
NSMaxY (windowFrame));
firstWindow = NO;
}
else
{
/*
* cascadeTopLeftFromPoint will "wrap" the point back to the
* top left if the normal cascading will cause the window to go
* off the screen. In Apple's implementation, this wraps to the
* extreme top of the screen, and offset only a small amount
* from the left.
*/
nextWindowLocation
static NSPoint nextWindowLocation = { 0.0, 0.0 };
/*
* cascadeTopLeftFromPoint will "wrap" the point back to the
* top left if the normal cascading will cause the window to go
* off the screen. In Apple's implementation, this wraps to the
* extreme top of the screen, and offset only a small amount
* from the left.
*/
nextWindowLocation
= [_window cascadeTopLeftFromPoint: nextWindowLocation];
}
}
[self windowDidLoad];

View file

@ -96,6 +96,22 @@ NSString *NSApplicationWillResignActiveNotification
NSString *NSApplicationWillUnhideNotification = @"ApplicationWillUnhide";
NSString *NSApplicationWillUpdateNotification = @"ApplicationWillUpdate";
// NSBitmapImageRep Global strings
NSString *NSImageCompressionMethod = @"NSImageCompressionMethod";
NSString *NSImageCompressionFactor = @"NSImageCompressionFactor";
NSString *NSImageDitherTransparency = @"NSImageDitherTransparency";
NSString *NSImageRGBColorTable = @"NSImageRGBColorTable";
NSString *NSImageInterlaced = @"NSImageInterlaced";
//NSString *NSImageColorSyncProfileData = @"NSImageColorSyncProfileData"; // Mac OS X only
//NSString *GSImageICCProfileData = @"GSImageICCProfileData"; // if & when GNUstep supports color management
NSString *NSImageFrameCount = @"NSImageFrameCount";
NSString *NSImageCurrentFrame = @"NSImageCurrentFrame";
NSString *NSImageCurrentFrameDuration = @"NSImageCurrentFrameDuration";
NSString *NSImageLoopCount = @"NSImageLoopCount";
NSString *NSImageGamma = @"NSImageGamma";
NSString *NSImageProgressive = @"NSImageProgressive";
//NSString *NSImageEXIFData = @"NSImageEXIFData"; // No support yet in GNUstep
// NSColor Global strings
NSString *NSCalibratedWhiteColorSpace = @"NSCalibratedWhiteColorSpace";
NSString *NSCalibratedBlackColorSpace = @"NSCalibratedBlackColorSpace";

View file

@ -75,5 +75,7 @@ extern NSTiffInfo* NSTiffGetInfo(int imageNumber, TIFF* image);
extern NSTiffColormap* NSTiffGetColormap(TIFF* image);
extern int NSTiffIsCodecConfigured(unsigned int codec);
#endif // _GNUstep_H_tiff

View file

@ -585,4 +585,60 @@ NSTiffGetColormap(TIFF* image)
return map;
}
int NSTiffIsCodecConfigured(unsigned int codec)
{
#if (TIFFLIB_VERSION >= 20041016)
// starting with version 3.7.0 we can ask libtiff what it is configured to do
return TIFFIsCODECConfigured(codec);
#else
// we check the tiffconf.h
#include <tiffconf.h>
#ifndef CCITT_SUPPORT
# define CCITT_SUPPORT 0
#else
# define CCITT_SUPPORT 1
#endif
#ifndef PACKBITS_SUPPORT
# define PACKBITS_SUPPORT 0
#else
# define PACKBITS_SUPPORT 1
#endif
#ifndef OJPEG_SUPPORT
# define OJPEG_SUPPORT 0
#else
# define OJPEG_SUPPORT 1
#endif
#ifndef LZW_SUPPORT
# define LZW_SUPPORT 0
#else
# define LZW_SUPPORT 1
#endif
#ifndef NEXT_SUPPORT
# define NEXT_SUPPORT 0
#else
# define NEXT_SUPPORT 1
#endif
#ifndef JPEG_SUPPORT
# define JPEG_SUPPORT 0
#else
# define JPEG_SUPPORT 1
#endif
/* If this fails, your libtiff is obsolete! Come to think of it
* if you even are compiling this part your libtiff is obsolete. */
switch (codec)
{
case COMPRESSION_NONE: return 1;
case COMPRESSION_CCITTFAX3: return CCITT_SUPPORT;
case COMPRESSION_CCITTFAX4: return CCITT_SUPPORT;
case COMPRESSION_JPEG: return JPEG_SUPPORT;
case COMPRESSION_PACKBITS: return PACKBITS_SUPPORT;
case COMPRESSION_OJPEG: return OJPEG_SUPPORT;
case COMPRESSION_LZW: return LZW_SUPPORT;
case COMPRESSION_NEXT: return NEXT_SUPPORT;
default:
return 0;
}
#endif
}