mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-23 20:01:11 +00:00
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:
parent
f92292517e
commit
8611a58783
19 changed files with 980 additions and 150 deletions
100
ChangeLog
100
ChangeLog
|
@ -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>
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:";
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
+ (BOOL) _bitmapIsGIF: (NSData *)imageData;
|
||||
- (id) _initBitmapFromGIF: (NSData *)imageData
|
||||
errorMessage: (NSString **)errorMsg;
|
||||
- (NSData *) _GIFRepresentationWithProperties: (NSDictionary *) properties
|
||||
errorMessage: (NSString **)errorMsg;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
@interface NSBitmapImageRep (PNG)
|
||||
+ (BOOL) _bitmapIsPNG: (NSData *)imageData;
|
||||
- (id) _initBitmapFromPNG: (NSData *)imageData;
|
||||
- (NSData *) _PNGRepresentationWithProperties: (NSDictionary *) properties;
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue