Skip to content

Commit

Permalink
<rdar://problem/6631355>: add support for native bitmaps
Browse files Browse the repository at this point in the history
(cherry picked from commit 5999a44)
  • Loading branch information
das committed Feb 27, 2009
1 parent c9fc1ac commit 54cfb1d
Showing 1 changed file with 143 additions and 164 deletions.
307 changes: 143 additions & 164 deletions tk/macosx/tkMacOSXBitmap.c
Expand Up @@ -14,35 +14,15 @@
* RCS: @(#) $Id$
*/

#include "tkMacOSXInt.h"

#ifdef MAC_OSX_TK_TODO
/*
* 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.
*/

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;

/*
Expand All @@ -51,25 +31,26 @@ 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}
};
#endif

#define builtInIconSize 32

/*
*----------------------------------------------------------------------
Expand All @@ -92,49 +73,79 @@ static BuiltInIcon builtInIcons[] = {
void
TkpDefineNativeBitmaps(void)
{
#ifdef MAC_OSX_TK_TODO
Tcl_HashTable *tablePtr = TkGetBitmapPredefTable();
BuiltInIcon *builtInPtr;

for (builtInPtr = builtInIcons; builtInPtr->name != NULL; builtInPtr++) {
Tcl_HashEntry *predefHashPtr;
const char * name;
Tk_Uid name;
int isNew;

name = Tk_GetUid(builtInPtr->name);
predefHashPtr = Tcl_CreateHashEntry(tablePtr, name, &isNew);
if (isNew) {
TkPredefBitmap *predefPtr = (TkPredefBitmap *)
ckalloc(sizeof(TkPredefBitmap));
NativeIcon *nativeIconPtr = (NativeIcon *)
ckalloc(sizeof(NativeIcon));

nativeIconPtr->id = builtInPtr->id;
nativeIconPtr->type = builtInPtr->type;
predefPtr->source = (char *) 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);
}
}
#endif
}

/*
*----------------------------------------------------------------------
*
* GetBitmapForIcon --
*
* Results:
* Bitmap for the given IconRef.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/

static Pixmap
GetBitmapForIcon(
Display *display,
IconRef icon)
{
TkMacOSXDrawingContext dc;
Pixmap pixmap;

pixmap = Tk_GetPixmap(display, None, builtInIconSize, builtInIconSize, 0);
if (TkMacOSXSetupDrawingContext(pixmap, NULL, 1, &dc)) {
if (dc.context) {
const CGAffineTransform t = { .a= 1, .b = 0, .c = 0, .d = -1,
.tx = 0, .ty = builtInIconSize };
const CGRect r = { .origin = { .x = 0, .y = 0 }, .size = {
.width = builtInIconSize, .height = builtInIconSize } };

CGContextConcatCTM(dc.context, t);
PlotIconRefInContext(dc.context, &r, kAlignNone,
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.
*
*----------------------------------------------------------------------
*/
Expand All @@ -144,59 +155,40 @@ TkpCreateNativeBitmap(
Display *display,
const char *source) /* Info about the icon to build. */
{
Pixmap pix;
#ifdef MAC_OSX_TK_TODO
Rect destRect;
CGrafPtr savePort;
Boolean portChanged;
const NativeIcon *nativeIconPtr;

pix = Tk_GetPixmap(display, None, 32, 32, 0);
portChanged = QDSwapPort(TkMacOSXGetDrawablePort(pix), &savePort);
Pixmap pixmap;
IconRef icon;
OSErr err;

nativeIconPtr = (const NativeIcon *) source;
SetRect(&destRect, 0, 0, 32, 32);
if (nativeIconPtr->type == TYPE1) {
RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF};

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);
}
}

if (portChanged) {
QDSwapPort(savePort, NULL);
err = ChkErr(GetIconRef, kOnSystemDisk, kSystemIconsCreator,
PTR2UINT(source), &icon);
if (err == noErr) {
pixmap = GetBitmapForIcon(display, icon);
ReleaseIconRef(icon);
} else {
pixmap = Tk_GetPixmap(display, None, builtInIconSize,
builtInIconSize, 0);
}
#else
pix = Tk_GetPixmap(display, None, 32, 32, 0);
#endif
return pix;
return pixmap;
}

/*
*----------------------------------------------------------------------
*
* TkpGetNativeAppBitmap --
*
* Add native bitmaps.
* Get a named native bitmap.
*
* Attemps to interpret the given name in order as:
* - NSImage named image name
* - NSImage path to image file
* - 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.
*
*----------------------------------------------------------------------
*/
Expand All @@ -208,82 +200,69 @@ TkpGetNativeAppBitmap(
int *width, /* The width & height of the bitmap. */
int *height)
{
Pixmap pix;
#ifdef MAC_OSX_TK_TODO
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.
*/

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);
Pixmap pixmap = None;
NSString *string = [NSString stringWithUTF8String:name];
NSImage *image = [NSImage imageNamed:string];

resource = GetNamedResource('cicn', nativeName);
if (resource != NULL) {
type = TYPE3;
} else {
resource = GetNamedResource('ICON', nativeName);
if (resource != NULL) {
type = TYPE2;
}
if (!image) {
image = [[[NSImage alloc] initWithContentsOfFile:string] autorelease];
}

if (resource == NULL) {
return (Pixmap) NULL;
if (!image) {
NSURL *url = [NSURL URLWithString:string];
if (url) {
image = [[[NSImage alloc] initWithContentsOfURL:url] autorelease];
}
}
if (image) {
TkMacOSXDrawingContext dc;
NSSize size = [image size];

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};
pixmap = Tk_GetPixmap(display, None, size.width, size.height, 0);
*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;

/*
* 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.
*/
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 {
Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman");
Tcl_DString ds;

RGBForeColor(&white);
PaintRect(&destRect);
GetResInfo(resource, &id, &theType, dummy);
ReleaseResource(resource);
resource = (Handle) GetCIcon(id);
PlotCIcon(&destRect, (CIconHandle) resource);
DisposeCIcon((CIconHandle) resource);
}
Tcl_UtfToExternalDString(encoding, name, -1, &ds);
if (Tcl_DStringLength(&ds) <= 4) {
char string[4] = {};
OSType iconType;
IconRef icon;
OSErr err;

*width = 32;
*height = 32;
if (portChanged) {
QDSwapPort(savePort, NULL);
memcpy(string, Tcl_DStringValue(&ds),
(size_t) Tcl_DStringLength(&ds));
iconType = (OSType) string[0] << 24 | (OSType) string[1] << 16 |
(OSType) string[2] << 8 | (OSType) string[3];
err = ChkErr(GetIconRef, kOnSystemDisk, kSystemIconsCreator,
iconType, &icon);
if (err == noErr) {
pixmap = GetBitmapForIcon(display, icon);
*width = builtInIconSize;
*height = builtInIconSize;
ReleaseIconRef(icon);
}
}
Tcl_DStringFree(&ds);
Tcl_FreeEncoding(encoding);
}
#else
pix = Tk_GetPixmap(display, None, 32, 32, 0);
*width = 32;
*height = 32;
#endif
return pix;
return pixmap;
}

/*
Expand Down

0 comments on commit 54cfb1d

Please sign in to comment.