More clipboard-related fixes for Basilisk / SheepShaver

This patch fixes one lingering problem with the 64-bit clipboard code; the way it was designed, the Mac clipboard was being cleared every time a single item was being requested by GetScrap, causing clipboards with multiple items to be unceremoniously whittled down to one. On the other hand, a similar issue was causing some items to get duplicated on the host pasteboard. This patch fixes the issue by making conversion between the host pasteboard and the Mac clipboard a singular operation; when the pasteboard data changes on the host side, it is all converted and sent to the Mac pasteboard at once, and similarly, all Mac clipboard data is sent to the host pasteboard in one operation. Also, data from the host side is copied to the Mac clipboard only if it has changed since the last check, which should improve performance as conversions will not be done over and over every time the Mac side checks whether the scrap has changed.

In addition, I've added a rudimentary PICT converter. It's rudimentary at the moment, only going in one direction, converting to PICT and not from PICT, and currently it always rasterizes the source image and creates a PICT containing bitmap data. However, it's a start, and it should solve Ronald's issue with copying images from OS X to Mac OS. In the future, more could possibly be added. I've put the new PICT code in the main source directory instead of in the MacOSX subdirectory, so that it can be used by other platforms if needed.

I would like to leave the license on the new PICT code as "Public Domain" if that is okay.

Thanks,
Charles
This commit is contained in:
Charles 2012-07-07 03:32:32 -05:00 committed by Alexei Svitkine
parent e1d132083b
commit 6f2635ee31
7 changed files with 523 additions and 89 deletions

View File

@ -30,6 +30,7 @@
#include "cpu_emulation.h"
#include "emul_op.h"
#include "autorelease.h"
#include "pict.h"
#define DEBUG 0
#include "debug.h"
@ -43,13 +44,14 @@
#define TYPE_STYL FOURCC('s','t','y','l')
static NSPasteboard *g_pboard;
static NSUInteger g_pb_change_count = 0;
// Flag for PutScrap(): the data was put by GetScrap(), don't bounce it back to the MacOS X side
static bool we_put_this_data = false;
static bool should_clear = false;
static NSMutableDictionary *macScrap;
static NSMutableDictionary *g_macScrap;
// flavor UTIs
@ -150,7 +152,7 @@ static ScriptCode ScriptNumberForFontID(int16_t fontID)
}
/*
* Get Mac's default text encoding
* Get Mac's default text encoding
*/
static TextEncoding MacDefaultTextEncoding()
@ -269,7 +271,7 @@ static NSData *ConvertToMacTextEncoding(NSAttributedString *aStr, NSArray **styl
}
/*
* Count all Mac font IDs on the system
* Count all Mac font IDs on the system
*/
static NSUInteger CountMacFonts()
@ -305,7 +307,7 @@ static NSUInteger CountMacFonts()
}
/*
* Get Mac font ID at index
* Get Mac font ID at index
*/
static int16_t MacFontIDAtIndex(NSUInteger index)
@ -377,7 +379,7 @@ static int16_t MacFontIDAtIndex(NSUInteger index)
}
/*
* List all font IDs on the system
* List all font IDs on the system
*/
static NSArray *ListMacFonts()
@ -395,7 +397,7 @@ static NSArray *ListMacFonts()
}
/*
* List all font IDs having a certain script
* List all font IDs having a certain script
*/
static NSArray *ListMacFontsForScript(ScriptCode script)
@ -411,7 +413,7 @@ static NSArray *ListMacFontsForScript(ScriptCode script)
}
/*
* Convert Mac font ID to font name
* Convert Mac font ID to font name
*/
static NSString *FontNameFromFontID(int16_t fontID)
@ -456,7 +458,7 @@ static NSString *FontNameFromFontID(int16_t fontID)
}
/*
* Convert font name to Mac font ID
* Convert font name to Mac font ID
*/
static int16_t FontIDFromFontName(NSString *fontName)
@ -506,7 +508,7 @@ static int16_t FontIDFromFontName(NSString *fontName)
}
/*
* Get font ID in desired script if possible; otherwise, try to get some font in the desired script.
* Get font ID in desired script if possible; otherwise, try to get some font in the desired script.
*/
static int16_t FontIDFromFontNameAndScript(NSString *fontName, ScriptCode script)
@ -536,7 +538,7 @@ static int16_t FontIDFromFontNameAndScript(NSString *fontName, ScriptCode script
}
/*
* Convert Mac TEXT/styl to attributed string
* Convert Mac TEXT/styl to attributed string
*/
static NSAttributedString *AttributedStringFromMacTEXTAndStyl(NSData *textData, NSData *stylData)
@ -667,7 +669,7 @@ static NSAttributedString *AttributedStringFromMacTEXTAndStyl(NSData *textData,
}
/*
* Append styl data for one text run
* Append styl data for one text run
*/
static void AppendStylRunData(NSMutableData *stylData, NSDictionary *attrs, ScriptCode script)
@ -739,7 +741,7 @@ static void AppendStylRunData(NSMutableData *stylData, NSDictionary *attrs, Scri
}
/*
* Convert attributed string to TEXT/styl
* Convert attributed string to TEXT/styl
*/
static NSData *ConvertToMacTEXTAndStyl(NSAttributedString *aStr, NSData **outStylData)
@ -789,10 +791,28 @@ static NSData *ConvertToMacTEXTAndStyl(NSAttributedString *aStr, NSData **outSty
}
/*
* Convert Mac TEXT/styl to RTF
* Get data of a particular flavor from the pasteboard
*/
static void WriteMacTEXTAndStylToPasteboard(NSData *textData, NSData *stylData)
static NSData *DataFromPasteboard(NSPasteboard *pboard, NSString *flavor)
{
NSArray *objs = [pboard readObjectsForClasses:[NSArray arrayWithObject:[NSPasteboardItem class]] options:nil];
for (NSPasteboardItem *eachItem in objs) {
NSData *data = [eachItem dataForType:flavor];
if ([data length])
return data;
}
return nil;
}
/*
* Convert Mac TEXT/styl to RTF
*/
static void WriteMacTEXTAndStylToPasteboard(NSPasteboard *pboard, NSData *textData, NSData *stylData)
{
NSMutableAttributedString *aStr = [AttributedStringFromMacTEXTAndStyl(textData, stylData) mutableCopy];
@ -810,23 +830,23 @@ static void WriteMacTEXTAndStylToPasteboard(NSData *textData, NSData *stylData)
// fix line endings
[[aStr mutableString] replaceOccurrencesOfString:@"\r" withString:@"\n" options:NSLiteralSearch range:NSMakeRange(0, [aStr length])];
[g_pboard writeObjects:[NSArray arrayWithObject:aStr]];
[pboard writeObjects:[NSArray arrayWithObject:aStr]];
}
/*
* Convert RTF to Mac TEXT/styl
* Convert RTF to Mac TEXT/styl
*/
static NSData *GetMacTEXTAndStylDataFromPasteboard(NSData **outStylData)
static NSData *MacTEXTAndStylDataFromPasteboard(NSPasteboard *pboard, NSData **outStylData)
{
NSMutableAttributedString *aStr;
NSArray *objs = [g_pboard readObjectsForClasses:[NSArray arrayWithObject:[NSAttributedString class]] options:nil];
NSArray *objs = [pboard readObjectsForClasses:[NSArray arrayWithObject:[NSAttributedString class]] options:nil];
if ([objs count]) {
aStr = [[objs objectAtIndex:0] mutableCopy];
} else {
objs = [g_pboard readObjectsForClasses:[NSArray arrayWithObject:[NSString class]] options:nil];
objs = [pboard readObjectsForClasses:[NSArray arrayWithObject:[NSString class]] options:nil];
if (![objs count])
return nil;
@ -859,7 +879,7 @@ void ClipInit(void)
D(bug("could not create Pasteboard\n"));
}
macScrap = [[NSMutableDictionary alloc] init];
g_macScrap = [[NSMutableDictionary alloc] init];
}
@ -872,12 +892,105 @@ void ClipExit(void)
[g_pboard release];
g_pboard = nil;
[macScrap release];
macScrap = nil;
[g_macScrap release];
g_macScrap = nil;
}
/*
* Zero Mac clipboard
* Convert an NSImage to PICT format.
*/
static NSData *ConvertImageToPICT(NSImage *image) {
if ([[image representations] count] == 0) {
return nil;
}
NSImageRep *rep = [[image representations] objectAtIndex:0];
NSUInteger width;
NSUInteger height;
if ([rep isKindOfClass:[NSBitmapImageRep class]]) {
width = [rep pixelsWide];
height = [rep pixelsHigh];
} else {
width = lrint([image size].width);
height = lrint([image size].height);
}
// create a new bitmap image rep in our desired format, following the advice here:
// https://developer.apple.com/library/mac/#releasenotes/Cocoa/AppKitOlderNotes.html#X10_6Notes
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:width
pixelsHigh:height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSCalibratedRGBColorSpace
bytesPerRow:width * 4
bitsPerPixel:32];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:bitmap]];
[rep draw];
[NSGraphicsContext restoreGraphicsState];
unsigned char *rgba = [bitmap bitmapData];
long bufSize = ConvertRGBAToPICT(NULL, 0, rgba, width, height);
NSData *pictData = nil;
if (bufSize > 0) {
uint8_t *buf = (uint8_t *)malloc(bufSize);
long pictSize = ConvertRGBAToPICT(buf, bufSize, rgba, width, height);
if (pictSize > 0)
pictData = [NSData dataWithBytes:buf length:pictSize];
free(buf);
}
[bitmap release];
return pictData;
}
/*
* Convert any images that may be on the clipboard to PICT format if possible.
*/
static NSData *MacPICTDataFromPasteboard(NSPasteboard *pboard)
{
// check if there's any PICT data on the pasteboard
NSData *pictData = DataFromPasteboard(pboard, (NSString *)kUTTypePICT);
if (pictData)
return pictData;
// now check to see if any images on the pasteboard have PICT representations
NSArray *objs = [pboard readObjectsForClasses:[NSArray arrayWithObject:[NSImage class]] options:nil];
for (NSImage *eachImage in objs) {
for (NSImageRep *eachRep in [eachImage representations]) {
if ([eachRep isKindOfClass:[NSPICTImageRep class]])
return [(NSPICTImageRep *)eachRep PICTRepresentation];
}
}
// Give up and perform the conversion ourselves
if ([objs count])
return ConvertImageToPICT([objs objectAtIndex:0]);
// If none of that worked, sorry, we're out of options
return nil;
}
/*
* Zero Mac clipboard
*/
static void ZeroMacClipboard()
@ -904,7 +1017,7 @@ static void ZeroMacClipboard()
}
/*
* Write data to Mac clipboard
* Write data to Mac clipboard
*/
static void WriteDataToMacClipboard(NSData *pbData, uint32_t type)
@ -948,6 +1061,8 @@ static void WriteDataToMacClipboard(NSData *pbData, uint32_t type)
r.a[0] = proc_area;
Execute68kTrap(0xa01f, &r); // DisposePtr
[g_macScrap setObject:pbData forKey:[NSNumber numberWithInteger:type]];
}
r.a[0] = scrap_area;
@ -955,6 +1070,80 @@ static void WriteDataToMacClipboard(NSData *pbData, uint32_t type)
}
}
/*
* Take all the data on host pasteboard and convert it to something the Mac understands if possible
*/
static void ConvertHostPasteboardToMacScrap()
{
ZeroMacClipboard();
NSData *stylData = nil;
NSData *textData = MacTEXTAndStylDataFromPasteboard(g_pboard, &stylData);
if (textData) {
if (stylData)
WriteDataToMacClipboard(stylData, TYPE_STYL);
WriteDataToMacClipboard(textData, TYPE_TEXT);
}
NSData *pictData = MacPICTDataFromPasteboard(g_pboard);
if (pictData)
WriteDataToMacClipboard(pictData, TYPE_PICT);
}
/*
* Take all the data on the Mac clipbord and convert it to something the host pasteboard understands if possible
*/
static void ConvertMacScrapToHostPasteboard()
{
BOOL wroteText = NO;
[g_pboard clearContents];
for (NSNumber *eachTypeNum in g_macScrap) AUTORELEASE_POOL {
uint32_t eachType = [eachTypeNum integerValue];
if (eachType == TYPE_TEXT || eachType == TYPE_STYL) {
if(wroteText)
continue;
NSData *textData;
NSData *stylData;
textData = [g_macScrap objectForKey:[NSNumber numberWithInteger:TYPE_TEXT]];
stylData = [g_macScrap objectForKey:[NSNumber numberWithInteger:TYPE_STYL]];
if (textData) {
WriteMacTEXTAndStylToPasteboard(g_pboard, textData, stylData);
wroteText = YES;
}
continue;
}
NSData *pbData = [g_macScrap objectForKey:eachTypeNum];
if (pbData) {
NSString *typeStr = GetUTIFromFlavor(eachType);
if(!typeStr)
continue;
NSPasteboardItem *pbItem = [[NSPasteboardItem alloc] init];
[pbItem setData:pbData forType:typeStr];
[g_pboard writeObjects:[NSArray arrayWithObject:pbItem]];
[pbItem release];
}
}
}
/*
* Mac application reads clipboard
*/
@ -964,52 +1153,18 @@ void GetScrap(void **handle, uint32_t type, int32_t offset)
D(bug("GetScrap handle %p, type %4.4s, offset %d\n", handle, (char *)&type, offset));
AUTORELEASE_POOL {
NSString *typeStr;
if (!g_pboard)
return;
if (!(typeStr = GetUTIFromFlavor(type)))
return;
if (type == TYPE_TEXT || type == TYPE_STYL) {
NSData *stylData = nil;
NSData *textData = GetMacTEXTAndStylDataFromPasteboard(&stylData);
if (textData) {
ZeroMacClipboard();
if (stylData)
WriteDataToMacClipboard(stylData, TYPE_STYL);
WriteDataToMacClipboard(textData, TYPE_TEXT);
return;
}
}
NSData *pbData = nil;
NSArray *objs = [g_pboard readObjectsForClasses:[NSArray arrayWithObject:[NSPasteboardItem class]] options:nil];
for (NSPasteboardItem *eachItem in objs) {
NSData *data = [eachItem dataForType:typeStr];
if ([data length]) {
pbData = data;
break;
}
}
if (pbData) {
ZeroMacClipboard();
WriteDataToMacClipboard(pbData, type);
if ([g_pboard changeCount] > g_pb_change_count) {
ConvertHostPasteboardToMacScrap();
g_pb_change_count = [g_pboard changeCount];
}
}
}
/*
* ZeroScrap() is called before a Mac application writes to the clipboard; clears out the previous contents
* ZeroScrap() is called before a Mac application writes to the clipboard; clears out the previous contents
*/
void ZeroScrap()
@ -1032,25 +1187,19 @@ void PutScrap(uint32_t type, void *scrap, int32_t length)
D(bug("PutScrap type %4.4s, data %p, length %ld\n", (char *)&type, scrap, (long)length));
AUTORELEASE_POOL {
NSString *typeStr;
if (!g_pboard)
return;
if (!(typeStr = GetUTIFromFlavor(type)))
return;
if (we_put_this_data) {
we_put_this_data = false;
return;
}
if (length <= 0)
return;
if (should_clear) {
[g_pboard clearContents];
[macScrap removeAllObjects];
[g_macScrap removeAllObjects];
should_clear = false;
}
@ -1058,24 +1207,11 @@ void PutScrap(uint32_t type, void *scrap, int32_t length)
if (!pbData)
return;
[macScrap setObject:pbData forKey:[NSNumber numberWithInteger:type]];
[g_macScrap setObject:pbData forKey:[NSNumber numberWithInteger:type]];
if (type == TYPE_TEXT || type == TYPE_STYL) {
NSData *textData;
NSData *stylData;
ConvertMacScrapToHostPasteboard();
textData = [macScrap objectForKey:[NSNumber numberWithInteger:TYPE_TEXT]];
stylData = [macScrap objectForKey:[NSNumber numberWithInteger:TYPE_STYL]];
if (textData) {
WriteMacTEXTAndStylToPasteboard(textData, stylData);
}
} else if (pbData) {
NSPasteboardItem *pbItem = [[[NSPasteboardItem alloc] init] autorelease];
[pbItem setData:pbData forType:typeStr];
[g_pboard writeObjects:[NSArray arrayWithObject:pbItem]];
}
// So that our PutScrap() patch won't bounce the data we just wrote back to the Mac clipboard
g_pb_change_count = [g_pboard changeCount];
}
}

View File

@ -744,7 +744,7 @@ if [[ "x$WANT_SDL_VIDEO" = "xyes" ]]; then
[AC_MSG_RESULT(yes); LP64_DEFINED=yes],
[AC_MSG_RESULT(no)])
if [[ "x$LP64_DEFINED" = "xyes" ]]; then
EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/clip_macosx64.mm"
EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/clip_macosx64.mm ../pict.c"
else
EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/clip_macosx.cpp"
fi

View File

@ -0,0 +1,29 @@
/*
* pict.h - convert an image to PICT.
*
* Currently creates a bitmap PICT resource; vector graphics are not preserved.
*
* By Charles Srstka.
*
* Public Domain. Do with it as you wish.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
* ConvertRGBAToPICT
*
* Converts image data, in 32-bit RGBA format, to PICT.
* Calling it first with NULL for the buffer will cause it to return a suggested buffer size.
* Returns the number of bytes actually written, or negative if something went wrong.
* However, this usually just means the buffer wasn't large enough.
*/
ssize_t ConvertRGBAToPICT(uint8_t *buf, unsigned long bufSize, uint8_t *rgbaPixels, uint16_t width, uint16_t height);
#ifdef __cplusplus
}
#endif

267
BasiliskII/src/pict.c Normal file
View File

@ -0,0 +1,267 @@
/*
* pict.c - convert an image to PICT.
*
* Currently creates a bitmap PICT resource; vector graphics are not preserved.
*
* By Charles Srstka.
*
* Public Domain. Do with it as you wish.
*
*/
/*
* PICT format:
*
* Size: 2 bytes
* Bounding Rect: 8 bytes
*
* This is followed by a series of opcodes.
* Each opcode is 1 byte long for a Version 1 PICT, or 2 bytes long for a Version 2 PICT.
* The ones we currently care about are:
*
* 0x0011 VersionOp: begins PICT version 2
* 0x02ff Version: identifies PICT version 2
* 0x0c00 HeaderOp: followed by 24 header bytes
* 4 bytes: 0xFFFFFFFF for regular v2 PICT or 0xFFFE0000 for extended v2 PICT
* 16 bytes: fixed-point bounding rectangle (or resolution, if an extended v2 PICT)
* 4 bytes: reserved
*
* 0x0001 Clip: set clipping region: followed by variable-sized region
* 0x001e DefHilite: set default highlight color
* 0x009b DirectBitsRgn: bitmap data
* pixMap: 50 bytes (PixMap)
* srcRect: 8 bytes (Rect)
* dstRect: 8 bytes (Rect)
* mode: 2 bytes (Mode)
* maskRgn: variable (Region)
* pixData: variable
* 0x00ff End of File
*/
/*
* PixMap format:
*
* baseAddr: Ptr (4 bytes)
* rowBytes: Integer (2 bytes)
* bounds: Rect (8 bytes)
* pmVersion: Integer (2 bytes)
* packType: Integer (2 bytes)
* packSize: LongInt (4 bytes)
* hRes: Fixed (4 bytes)
* vRes: Fixed (4 bytes)
* pixelType: Integer (2 bytes)
* pixelSize: Integer (2 bytes)
* cmpCount: Integer (2 bytes)
* cmpSize: Integer (2 bytes)
* planeBytes: LongInt (4 bytes)
* pmTable: CTabHandle (4 bytes)
* pmReserved: LongInt (4 bytes)
*/
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <stdint.h>
static ssize_t CompressUsingRLE(uint8_t *row, uint16_t uncmpLength, uint8_t *outBuf, size_t bufSize)
{
int byteCountLength = 1 + (uncmpLength > 250);
uint16_t cmpCursor = byteCountLength;
uint16_t cursor = 0;
// enough to output the data uncompressed if we have to, plus the length bytes
size_t maxSize = byteCountLength + uncmpLength + (uncmpLength + 126) / 127;
int outOfRoom = 0;
uint16_t cmpLength;
if (row == NULL || outBuf == NULL || bufSize == 0)
return maxSize;
while (cursor < uncmpLength) {
uint8_t byte = row[cursor++];
uint8_t nextByte;
if (cursor < uncmpLength && (nextByte = row[cursor]) == byte) {
int8_t matches = 1;
while (++cursor < uncmpLength && matches < 127 && row[cursor] == byte) {
matches++;
}
if(cmpCursor + 2 > bufSize) {
outOfRoom = 1;
break;
}
outBuf[cmpCursor++] = -matches;
outBuf[cmpCursor++] = byte;
} else {
uint8_t literals = 0;
uint8_t i;
while (cursor + literals + 1 < uncmpLength && literals < 127 && nextByte != (nextByte = row[cursor + literals + 1])) {
literals++;
}
if(cmpCursor + 2 + literals > bufSize) {
outOfRoom = 1;
break;
}
outBuf[cmpCursor++] = literals;
outBuf[cmpCursor++] = byte;
for (i = 0; i < literals; i++) {
outBuf[cmpCursor++] = row[cursor++];
}
}
}
if(outOfRoom) {
// Trying to compress this just made it larger; just output the data uncompressed instead
if(bufSize < maxSize) {
// sorry folks, don't have enough buffer
return -1;
}
cursor = 0;
cmpCursor = byteCountLength;
while (cursor < uncmpLength) {
uint8_t bytesToCopy = uncmpLength - cursor > 128 ? 128 : uncmpLength - cursor;
outBuf[cmpCursor++] = bytesToCopy - 1;
memcpy(outBuf + cmpCursor, row + cursor, bytesToCopy); cmpCursor += bytesToCopy; cursor += bytesToCopy;
}
cmpLength = cmpCursor - 1;
}
cmpLength = cmpCursor - byteCountLength;
if (byteCountLength == 2) {
outBuf[0] = cmpLength >> 8;
outBuf[1] = cmpLength & 0xff;
} else {
outBuf[0] = cmpLength;
}
return cmpCursor;
}
ssize_t ConvertRGBAToPICT(uint8_t *buf, unsigned long bufSize, uint8_t *rgbaPixels, uint16_t width, uint16_t height)
{
unsigned long initialSize = (10 /* size + rect */ +
6 /* initial opcodes */ +
24 /* header */ +
12 /* clip region */ +
2 /* DefHilite */ +
70 /* DirectBitsRgn - pixData - maskRgn */ +
10 /* maskRgn */);
#define RECT_SIZE 8
#define REGION_SIZE 10
#define FIXED_RECT_SIZE 16
char rect[RECT_SIZE] = {0, 0, 0, 0, height >> 8, height & 0xff, width >> 8, width & 0xff };
char region[REGION_SIZE] = { 0x00, 0x0a, rect[0], rect[1], rect[2], rect[3], rect[4], rect[5], rect[6], rect[7] };
char fixedRect[FIXED_RECT_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, width >> 8, width & 0xff, 0, 0, height >> 8, height & 0xff, 0, 0 };
uint32_t hDPI = htonl(0x00480000); // 72 dpi
uint32_t vDPI = hDPI;
uint16_t bytesPerPixel = 4; // RGBA
uint16_t bytesPerRow = width * bytesPerPixel;
unsigned long cursor = 2; // size bytes filled in at the end
ssize_t cmpBufSize = CompressUsingRLE(NULL, bytesPerRow, NULL, 0);
uint8_t cmpBuf[cmpBufSize];
uint16_t i;
if (buf == NULL || bufSize == 0) {
// Give an upper bound for the buffer size.
return initialSize + height * cmpBufSize + 2;
}
if (bufSize < initialSize) {
return -1;
}
memcpy(buf + cursor, rect, RECT_SIZE); cursor += RECT_SIZE;
buf[cursor++] = 0x00; buf[cursor++] = 0x11; buf[cursor++] = 0x02; buf[cursor++] = 0xff;
buf[cursor++] = 0x0c; buf[cursor++] = 0x00;
buf[cursor++] = 0xff; buf[cursor++] = 0xff; buf[cursor++] = 0xff; buf[cursor++] = 0xff;
memcpy(buf + cursor, fixedRect, FIXED_RECT_SIZE); cursor += FIXED_RECT_SIZE;
memset(buf + cursor, '\0', 4); cursor += 4;
buf[cursor++] = 0x00; buf[cursor++] = 0x1e;
buf[cursor++] = 0x00; buf[cursor++] = 0x01;
memcpy(buf + cursor, region, REGION_SIZE); cursor += REGION_SIZE;
buf[cursor++] = 0x00; buf[cursor++] = 0x9b;
memset(buf + cursor, '\0', 4); cursor += 4; // I think this pointer isn't used
buf[cursor++] = (bytesPerRow >> 8) | 0x80; buf[cursor++] = bytesPerRow & 0xff; // rowBytes
memcpy(buf + cursor, rect, RECT_SIZE); cursor += RECT_SIZE; //bounds
buf[cursor++] = 0x00; buf[cursor++] = 0x00; // pmVersion
buf[cursor++] = 0x00; buf[cursor++] = 0x04; // packType
buf[cursor++] = 0x00; buf[cursor++] = 0x00; buf[cursor++] = 0x00; buf[cursor++] = 0x00; // packSize is always 0
memcpy(buf + cursor, &hDPI, 4); cursor += 4; // hRes
memcpy(buf + cursor, &vDPI, 4); cursor += 4; // vRes
buf[cursor++] = 0x00; buf[cursor++] = 0x10; // pixelType; direct device
buf[cursor++] = 0x00; buf[cursor++] = 0x20; // pixelSize; 32 bits per pixel
buf[cursor++] = bytesPerPixel >> 8; buf[cursor++] = bytesPerPixel & 0xff; // components per pixel
buf[cursor++] = 0x00; buf[cursor++] = 0x08; // 8 bits per component
memset(buf + cursor, '\0', 4); cursor += 4; // planeBytes isn't used
memset(buf + cursor, '\0', 4); cursor += 4; // don't think we need pmTable
memset(buf + cursor, '\0', 4); cursor += 4; // reserved
memcpy(buf + cursor, rect, RECT_SIZE); cursor += RECT_SIZE;
memcpy(buf + cursor, rect, RECT_SIZE); cursor += RECT_SIZE;
buf[cursor++] = 0x00; buf[cursor++] = 0x00; // no transfer mode
memcpy(buf + cursor, region, REGION_SIZE); cursor += REGION_SIZE;
for (i = 0; i < height; i++) {
uint8_t row[bytesPerRow];
ssize_t cmpLength;
uint16_t j;
for (j = 0; j < width; j++) {
row[j] = rgbaPixels[i * bytesPerRow + j * bytesPerPixel + 3];
row[width + j] = rgbaPixels[i * bytesPerRow + j * bytesPerPixel];
row[width * 2 + j] = rgbaPixels[i * bytesPerRow + j * bytesPerPixel + 1];
row[width * 3 + j] = rgbaPixels[i * bytesPerRow + j * bytesPerPixel + 2];
}
cmpLength = CompressUsingRLE(row, bytesPerRow, cmpBuf, cmpBufSize);
if (cmpLength < 0 || cursor + cmpLength > bufSize)
return -1;
memcpy(buf + cursor, cmpBuf, cmpLength); cursor += cmpLength;
}
// Fun fact: forgetting to put 0x00ff at the end of a PICT picture causes the entire
// Classic Mac OS to crash when it tries to read it! Don't ask me how I learned this.
if (cursor + 2 > bufSize)
return -1;
buf[cursor++] = 0x00; buf[cursor++] = 0xff;
if(cursor > UINT16_MAX) {
buf[0] = buf[1] = 0xff;
} else {
buf[0] = cursor >> 8;
buf[1] = cursor & 0xff;
}
return cursor;
}

View File

@ -716,7 +716,7 @@ if [[ "x$WANT_SDL_VIDEO" = "xyes" ]]; then
[AC_MSG_RESULT(yes); LP64_DEFINED=yes],
[AC_MSG_RESULT(no)])
if [[ "x$LP64_DEFINED" = "xyes" ]]; then
EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/clip_macosx64.mm"
EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/clip_macosx64.mm ../pict.c"
else
EXTRASYSSRCS="$EXTRASYSSRCS ../MacOSX/clip_macosx.cpp"
fi

View File

@ -0,0 +1 @@
../../../BasiliskII/src/include/pict.h

1
SheepShaver/src/pict.c Symbolic link
View File

@ -0,0 +1 @@
../../BasiliskII/src/pict.c