summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXBitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'macosx/tkMacOSXBitmap.c')
-rw-r--r--macosx/tkMacOSXBitmap.c483
1 files changed, 334 insertions, 149 deletions
diff --git a/macosx/tkMacOSXBitmap.c b/macosx/tkMacOSXBitmap.c
index 82771d4..62faae1 100644
--- a/macosx/tkMacOSXBitmap.c
+++ b/macosx/tkMacOSXBitmap.c
@@ -4,33 +4,16 @@
* This file handles the implementation of native bitmaps.
*
* Copyright (c) 1996-1997 Sun Microsystems, Inc.
- * Copyright 2001, Apple Computer, Inc.
- * Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2001-2009, Apple Inc.
+ * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkMacOSXBitmap.c,v 1.9 2009/02/27 23:23:36 nijtmans Exp $
+ * RCS: @(#) $Id: tkMacOSXBitmap.c,v 1.10 2009/06/29 14:35:01 das Exp $
*/
-#include "tkMacOSXInt.h"
-
-/*
- * Depending on the resource type there are different ways to
- * draw native icons.
- */
-#define TYPE1 0 /* Family icon suite. */
-#define TYPE2 1 /* ICON resource. */
-#define TYPE3 2 /* cicn resource. */
-
-/*
- * This data structure describes the id and type of a given icon.
- * It is used as the source for native icons.
- */
-typedef struct {
- int id; /* Resource Id for Icon. */
- long int type; /* Type of icon. */
-} NativeIcon;
+#include "tkMacOSXPrivate.h"
/*
* This structure holds information about native bitmaps.
@@ -38,9 +21,7 @@ typedef struct {
typedef struct {
const char *name; /* Name of icon. */
- long int type; /* Type of icon. */
- int id; /* Id of icon. */
- int size; /* Size of icon. */
+ OSType iconType; /* OSType of icon. */
} BuiltInIcon;
/*
@@ -49,24 +30,42 @@ typedef struct {
*/
static BuiltInIcon builtInIcons[] = {
- {"document", TYPE1, kGenericDocumentIconResource, 32},
- {"stationery", TYPE1, kGenericStationeryIconResource, 32},
- {"edition", TYPE1, kGenericEditionFileIconResource, 32},
- {"application", TYPE1, kGenericApplicationIconResource, 32},
- {"accessory", TYPE1, kGenericDeskAccessoryIconResource, 32},
- {"folder", TYPE1, kGenericFolderIconResource, 32},
- {"pfolder", TYPE1, kPrivateFolderIconResource, 32},
- {"trash", TYPE1, kTrashIconResource, 32},
- {"floppy", TYPE1, kFloppyIconResource, 32},
- {"ramdisk", TYPE1, kGenericRAMDiskIconResource, 32},
- {"cdrom", TYPE1, kGenericCDROMIconResource, 32},
- {"preferences", TYPE1, kGenericPreferencesIconResource, 32},
- {"querydoc", TYPE1, kGenericQueryDocumentIconResource, 32},
- {"stop", TYPE2, kStopIcon, 32},
- {"note", TYPE2, kNoteIcon, 32},
- {"caution", TYPE2, kCautionIcon, 32},
- {NULL, 0, 0, 0}
+ {"document", kGenericDocumentIcon},
+ {"stationery", kGenericStationeryIcon},
+ {"edition", kGenericEditionFileIcon},
+ {"application", kGenericApplicationIcon},
+ {"accessory", kGenericDeskAccessoryIcon},
+ {"folder", kGenericFolderIcon},
+ {"pfolder", kPrivateFolderIcon},
+ {"trash", kTrashIcon},
+ {"floppy", kGenericFloppyIcon},
+ {"ramdisk", kGenericRAMDiskIcon},
+ {"cdrom", kGenericCDROMIcon},
+ {"preferences", kGenericPreferencesIcon},
+ {"querydoc", kGenericQueryDocumentIcon},
+ {"stop", kAlertStopIcon},
+ {"note", kAlertNoteIcon},
+ {"caution", kAlertCautionIcon},
+ {NULL}
};
+
+#define builtInIconSize 32
+
+static Tcl_HashTable iconBitmapTable = {};
+typedef struct {
+ int kind, width, height;
+ char *value;
+} IconBitmap;
+
+static const char *const iconBitmapOptionStrings[] = {
+ "-file", "-fileType", "-osType", "-systemType", "-namedImage",
+ "-imageFile", NULL
+};
+enum iconBitmapOptions {
+ ICON_FILE, ICON_FILETYPE, ICON_OSTYPE, ICON_SYSTEMTYPE, ICON_NAMEDIMAGE,
+ ICON_IMAGEFILE,
+};
+
/*
*----------------------------------------------------------------------
@@ -94,7 +93,7 @@ TkpDefineNativeBitmaps(void)
for (builtInPtr = builtInIcons; builtInPtr->name != NULL; builtInPtr++) {
Tcl_HashEntry *predefHashPtr;
- const char * name;
+ Tk_Uid name;
int isNew;
name = Tk_GetUid(builtInPtr->name);
@@ -102,14 +101,9 @@ TkpDefineNativeBitmaps(void)
if (isNew) {
TkPredefBitmap *predefPtr = (TkPredefBitmap *)
ckalloc(sizeof(TkPredefBitmap));
- NativeIcon *nativeIconPtr = (NativeIcon *)
- ckalloc(sizeof(NativeIcon));
-
- nativeIconPtr->id = builtInPtr->id;
- nativeIconPtr->type = builtInPtr->type;
- predefPtr->source = nativeIconPtr;
- predefPtr->width = builtInPtr->size;
- predefPtr->height = builtInPtr->size;
+ predefPtr->source = UINT2PTR(builtInPtr->iconType);
+ predefPtr->width = builtInIconSize;
+ predefPtr->height = builtInIconSize;
predefPtr->native = 1;
Tcl_SetHashValue(predefHashPtr, predefPtr);
}
@@ -119,17 +113,54 @@ TkpDefineNativeBitmaps(void)
/*
*----------------------------------------------------------------------
*
+ * GetBitmapForIcon --
+ *
+ * Results:
+ * Bitmap for the given IconRef.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Pixmap
+GetBitmapForIcon(
+ Display *display,
+ IconRef icon,
+ CGSize size)
+{
+ TkMacOSXDrawingContext dc;
+ Pixmap pixmap;
+
+ pixmap = Tk_GetPixmap(display, None, size.width, size.height, 0);
+ if (TkMacOSXSetupDrawingContext(pixmap, NULL, 1, &dc)) {
+ if (dc.context) {
+ const CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1,
+ .tx = 0, .ty = size.height };
+ const CGRect r = { .origin = { .x = 0, .y = 0 }, .size = size };
+
+ CGContextConcatCTM(dc.context, t);
+ PlotIconRefInContext(dc.context, &r, kAlignAbsoluteCenter,
+ kTransformNone, NULL, kPlotIconRefNormalFlags, icon);
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+ }
+ return pixmap;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkpCreateNativeBitmap --
*
- * Add native bitmaps.
+ * Create native bitmap.
*
* Results:
- * A standard Tcl result. If an error occurs then TCL_ERROR is
- * returned and a message is left in the interp's result.
+ * Native bitmap.
*
* Side effects:
- * "Name" is entered into the bitmap table and may be used from
- * here on to refer to the given bitmap.
+ * None.
*
*----------------------------------------------------------------------
*/
@@ -139,39 +170,56 @@ TkpCreateNativeBitmap(
Display *display,
const void *source) /* Info about the icon to build. */
{
- Pixmap pix;
- Rect destRect;
- CGrafPtr savePort;
- Boolean portChanged;
- const NativeIcon *nativeIconPtr;
-
- pix = Tk_GetPixmap(display, None, 32, 32, 0);
- portChanged = QDSwapPort(TkMacOSXGetDrawablePort(pix), &savePort);
-
- nativeIconPtr = (const NativeIcon *) source;
- SetRect(&destRect, 0, 0, 32, 32);
- if (nativeIconPtr->type == TYPE1) {
- RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF};
+ Pixmap pixmap;
+ IconRef icon;
+ OSErr err;
- RGBForeColor(&white);
- PaintRect(&destRect);
- PlotIconID(&destRect, atAbsoluteCenter, ttNone, nativeIconPtr->id);
- } else if (nativeIconPtr->type == TYPE2) {
- Handle icon = GetIcon(nativeIconPtr->id);
-
- if (icon != NULL) {
- RGBColor black = {0, 0, 0};
-
- RGBForeColor(&black);
- PlotIcon(&destRect, icon);
- ReleaseResource(icon);
- }
+ err = ChkErr(GetIconRef, kOnSystemDisk, kSystemIconsCreator,
+ PTR2UINT(source), &icon);
+ if (err == noErr) {
+ pixmap = GetBitmapForIcon(display, icon, CGSizeMake(builtInIconSize,
+ builtInIconSize));
+ ReleaseIconRef(icon);
+ } else {
+ pixmap = Tk_GetPixmap(display, None, builtInIconSize,
+ builtInIconSize, 0);
}
+ return pixmap;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * OSTypeFromString --
+ *
+ * Helper to convert string to OSType.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * t is set to OSType if conversion successful.
+ *
+ *----------------------------------------------------------------------
+ */
- if (portChanged) {
- QDSwapPort(savePort, NULL);
+static int
+OSTypeFromString(const char *s, OSType *t) {
+ int result = TCL_ERROR;
+ Tcl_DString ds;
+ Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman");
+
+ Tcl_UtfToExternalDString(encoding, s, -1, &ds);
+ if (Tcl_DStringLength(&ds) <= 4) {
+ char string[4] = {};
+ memcpy(string, Tcl_DStringValue(&ds), (size_t) Tcl_DStringLength(&ds));
+ *t = (OSType) string[0] << 24 | (OSType) string[1] << 16 |
+ (OSType) string[2] << 8 | (OSType) string[3];
+ result = TCL_OK;
}
- return pix;
+ Tcl_DStringFree(&ds);
+ Tcl_FreeEncoding(encoding);
+ return result;
}
/*
@@ -179,15 +227,19 @@ TkpCreateNativeBitmap(
*
* TkpGetNativeAppBitmap --
*
- * Add native bitmaps.
+ * Get a named native bitmap.
+ *
+ * Attemps to interpret the given name in order as:
+ * - name defined by ::tk::mac::iconBitmap
+ * - NSImage named image name
+ * - NSImage url string
+ * - 4-char OSType of IconServices icon
*
* Results:
- * A standard Tcl result. If an error occurs then TCL_ERROR is
- * returned and a message is left in the interp's result.
+ * Native bitmap or None.
*
* Side effects:
- * "Name" is entered into the bitmap table and may be used from
- * here on to refer to the given bitmap.
+ * None.
*
*----------------------------------------------------------------------
*/
@@ -199,74 +251,207 @@ TkpGetNativeAppBitmap(
int *width, /* The width & height of the bitmap. */
int *height)
{
- Pixmap pix;
- CGrafPtr savePort;
- Boolean portChanged;
- Rect destRect;
- Handle resource;
- int type = -1, destWrote;
- Str255 nativeName;
- Tcl_Encoding encoding;
-
- /*
- * macRoman is the encoding that the resource fork uses.
- */
+ Tcl_HashEntry *hPtr;
+ Pixmap pixmap = None;
+ NSString *string;
+ NSImage *image = nil;
+ NSSize size = { .width = builtInIconSize, .height = builtInIconSize };
- encoding = Tcl_GetEncoding(NULL, "macRoman");
- Tcl_UtfToExternal(NULL, encoding, name, strlen(name), 0, NULL,
- (char *) &nativeName[1], 255, NULL, &destWrote, NULL);
- nativeName[0] = destWrote;
- Tcl_FreeEncoding(encoding);
-
- resource = GetNamedResource('cicn', nativeName);
- if (resource != NULL) {
- type = TYPE3;
+ if (iconBitmapTable.buckets &&
+ (hPtr = Tcl_FindHashEntry(&iconBitmapTable, name))) {
+ OSType type;
+ IconBitmap *iconBitmap = Tcl_GetHashValue(hPtr);
+ name = NULL;
+ size = NSMakeSize(iconBitmap->width, iconBitmap->height);
+ switch (iconBitmap->kind) {
+ case ICON_FILE:
+ string = [[NSString stringWithUTF8String:iconBitmap->value]
+ stringByExpandingTildeInPath];
+ image = [[NSWorkspace sharedWorkspace] iconForFile:string];
+ break;
+ case ICON_FILETYPE:
+ string = [NSString stringWithUTF8String:iconBitmap->value];
+ image = [[NSWorkspace sharedWorkspace] iconForFileType:string];
+ break;
+ case ICON_OSTYPE:
+ if (OSTypeFromString(iconBitmap->value, &type) == TCL_OK) {
+ string = NSFileTypeForHFSTypeCode(type);
+ image = [[NSWorkspace sharedWorkspace] iconForFileType:string];
+ }
+ break;
+ case ICON_SYSTEMTYPE:
+ name = iconBitmap->value;
+ break;
+ case ICON_NAMEDIMAGE:
+ string = [NSString stringWithUTF8String:iconBitmap->value];
+ image = [NSImage imageNamed:string];
+ break;
+ case ICON_IMAGEFILE:
+ string = [[NSString stringWithUTF8String:iconBitmap->value]
+ stringByExpandingTildeInPath];
+ image = [[[NSImage alloc] initWithContentsOfFile:string]
+ autorelease];
+ break;
+ }
+ if (image) {
+ [image setSize:size];
+ }
} else {
- resource = GetNamedResource('ICON', nativeName);
- if (resource != NULL) {
- type = TYPE2;
+ string = [NSString stringWithUTF8String:name];
+ image = [NSImage imageNamed:string];
+ if (!image) {
+ NSURL *url = [NSURL URLWithString:string];
+ if (url) {
+ image = [[[NSImage alloc] initWithContentsOfURL:url]
+ autorelease];
+ }
+ }
+ if (image) {
+ size = [image size];
}
}
+ if (image) {
+ TkMacOSXDrawingContext dc;
+ int depth = 0;
- if (resource == NULL) {
- return (Pixmap) NULL;
- }
-
- pix = Tk_GetPixmap(display, None, 32, 32, 0);
- portChanged = QDSwapPort(TkMacOSXGetDrawablePort(pix), &savePort);
-
- SetRect(&destRect, 0, 0, 32, 32);
- if (type == TYPE2) {
- RGBColor black = {0, 0, 0};
+#ifdef MAC_OSX_TK_TODO
+ for (NSImageRep *r in [image representations]) {
+ NSInteger bitsPerSample = [r bitsPerSample];
+ if (bitsPerSample && bitsPerSample > depth) {
+ depth = bitsPerSample;
+ };
+ }
+ if (depth == 1) {
+ /* TODO: convert BW NSImage to CGImageMask */
+ }
+#endif
+ pixmap = Tk_GetPixmap(display, None, size.width, size.height, depth);
+ *width = size.width;
+ *height = size.height;
+ if (TkMacOSXSetupDrawingContext(pixmap, NULL, 1, &dc)) {
+ if (dc.context) {
+ CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1,
+ .tx = 0, .ty = size.height};
- RGBForeColor(&black);
- PlotIcon(&destRect, resource);
- ReleaseResource(resource);
- } else if (type == TYPE3) {
- RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF};
- short id;
- ResType theType;
- Str255 dummy;
+ CGContextConcatCTM(dc.context, t);
+ [NSGraphicsContext saveGraphicsState];
+ [NSGraphicsContext setCurrentContext:[NSGraphicsContext
+ graphicsContextWithGraphicsPort:dc.context flipped:NO]];
+ [image drawAtPoint:NSZeroPoint fromRect:NSZeroRect
+ operation:NSCompositeCopy fraction:1.0];
+ [NSGraphicsContext restoreGraphicsState];
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+ }
+ } else if (name) {
+ OSType iconType;
+ if (OSTypeFromString(name, &iconType) == TCL_OK) {
+ IconRef icon;
+ OSErr err = ChkErr(GetIconRef, kOnSystemDisk, kSystemIconsCreator,
+ iconType, &icon);
+ if (err == noErr) {
+ pixmap = GetBitmapForIcon(display, icon, NSSizeToCGSize(size));
+ *width = size.width;
+ *height = size.height;
+ ReleaseIconRef(icon);
+ }
+ }
+ }
+ return pixmap;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXIconBitmapObjCmd --
+ *
+ * Implements the ::tk::mac::iconBitmap command.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * none
+ *
+ *----------------------------------------------------------------------
+ */
- /*
- * We need to first paint the background white. Also, for some reason
- * we *must* use GetCIcon instead of GetNamedResource for PlotCIcon to
- * work - so we use GetResInfo to get the id.
- */
+int
+TkMacOSXIconBitmapObjCmd(
+ ClientData clientData, /* Unused. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tcl_HashEntry *hPtr;
+ int i = 1, len, isNew, result = TCL_ERROR;
+ const char *name, *value;
+ IconBitmap ib, *iconBitmap;
- RGBForeColor(&white);
- PaintRect(&destRect);
- GetResInfo(resource, &id, &theType, dummy);
- ReleaseResource(resource);
- resource = (Handle) GetCIcon(id);
- PlotCIcon(&destRect, (CIconHandle) resource);
- DisposeCIcon((CIconHandle) resource);
+ if (objc != 6) {
+ Tcl_WrongNumArgs(interp, 1, objv, "name width height "
+ "-file|-fileType|-osType|-systemType|-namedImage|-imageFile "
+ "value");
+ goto end;
}
-
- *width = 32;
- *height = 32;
- if (portChanged) {
- QDSwapPort(savePort, NULL);
+ name = Tcl_GetStringFromObj(objv[i++], &len);
+ if (!len) {
+ Tcl_AppendResult(interp, "empty bitmap name", NULL);
+ goto end;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[i++], &ib.width) != TCL_OK) {
+ goto end;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[i++], &ib.height) != TCL_OK) {
+ goto end;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[i++], iconBitmapOptionStrings,
+ "kind", TCL_EXACT, &ib.kind) != TCL_OK) {
+ goto end;
+ }
+ value = Tcl_GetStringFromObj(objv[i++], &len);
+ if (!len) {
+ Tcl_AppendResult(interp, "empty bitmap value", NULL);
+ goto end;
+ }
+#if 0
+ if ((kind == ICON_TYPE || kind == ICON_SYSTEM)) {
+ Tcl_DString ds;
+ Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman");
+ Tcl_UtfToExternalDString(encoding, value, -1, &ds);
+ len = Tcl_DStringLength(&ds);
+ Tcl_DStringFree(&ds);
+ Tcl_FreeEncoding(encoding);
+ if (len > 4) {
+ Tcl_AppendResult(interp, "invalid bitmap value", NULL);
+ goto end;
+ }
}
- return pix;
+#endif
+ ib.value = ckalloc(len);
+ strcpy(ib.value, value);
+ if (!iconBitmapTable.buckets) {
+ Tcl_InitHashTable(&iconBitmapTable, TCL_STRING_KEYS);
+ }
+ hPtr = Tcl_CreateHashEntry(&iconBitmapTable, name, &isNew);
+ if (!isNew) {
+ iconBitmap = Tcl_GetHashValue(hPtr);
+ ckfree(iconBitmap->value);
+ } else {
+ iconBitmap = (IconBitmap *) ckalloc(sizeof(IconBitmap));
+ Tcl_SetHashValue(hPtr, iconBitmap);
+ }
+ *iconBitmap = ib;
+ result = TCL_OK;
+end:
+ return result;
}
+
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */