1067 lines
25 KiB
C
1067 lines
25 KiB
C
/*
|
||
* tkMacDraw.c --
|
||
*
|
||
* This file contains functions that preform drawing to
|
||
* Xlib windows. Most of the functions simple emulate
|
||
* Xlib functions.
|
||
*
|
||
* Copyright (c) 1995-1996 Sun Microsystems, Inc.
|
||
*
|
||
* See the file "license.terms" for information on usage and redistribution
|
||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||
*
|
||
* SCCS: @(#) tkMacDraw.c 1.43 96/09/05 13:38:18
|
||
*/
|
||
|
||
#include "tkInt.h"
|
||
#include "X.h"
|
||
#include "Xlib.h"
|
||
#include <stdio.h>
|
||
#include <tcl.h>
|
||
|
||
#include <Windows.h>
|
||
#include <Fonts.h>
|
||
#include <QDOffscreen.h>
|
||
#include "tkMacInt.h"
|
||
|
||
#ifndef PI
|
||
# define PI 3.14159265358979323846
|
||
#endif
|
||
|
||
/*
|
||
* Temporary region that can be reused.
|
||
*/
|
||
static RgnHandle tmpRgn = NULL;
|
||
|
||
static PixPatHandle gPenPat = NULL;
|
||
|
||
/*
|
||
* Prototypes for functions used only in this file.
|
||
*/
|
||
static BitMapPtr MakeStippleMap _ANSI_ARGS_((Drawable drawable,
|
||
Drawable stipple));
|
||
static unsigned char InvertByte _ANSI_ARGS_((unsigned char data));
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XCopyArea --
|
||
*
|
||
* Copies data from one drawable to another using block transfer
|
||
* routines.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Data is moved from a window or bitmap to a second window or
|
||
* bitmap.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
XCopyArea(display, src, dest, gc, src_x, src_y, width, height, dest_x, dest_y)
|
||
Display* display;
|
||
Drawable src;
|
||
Drawable dest;
|
||
GC gc;
|
||
int src_x;
|
||
int src_y;
|
||
unsigned int width;
|
||
unsigned int height;
|
||
int dest_x;
|
||
int dest_y;
|
||
{
|
||
Rect srcRect, destRect;
|
||
BitMapPtr srcBit, destBit;
|
||
MacDrawable *srcDraw = (MacDrawable *) src;
|
||
MacDrawable *destDraw = (MacDrawable *) dest;
|
||
GWorldPtr srcPort, destPort;
|
||
CGrafPtr saveWorld;
|
||
GDHandle saveDevice;
|
||
short tmode;
|
||
|
||
destPort = TkMacGetDrawablePort(dest);
|
||
srcPort = TkMacGetDrawablePort(src);
|
||
|
||
display->request++;
|
||
GetGWorld(&saveWorld, &saveDevice);
|
||
SetGWorld(destPort, NULL);
|
||
|
||
TkMacSetUpClippingRgn(dest);
|
||
|
||
srcBit = &((GrafPtr) srcPort)->portBits;
|
||
destBit = &((GrafPtr) destPort)->portBits;
|
||
SetRect(&srcRect, (short) (srcDraw->xOff + src_x),
|
||
(short) (srcDraw->yOff + src_y),
|
||
(short) (srcDraw->xOff + src_x + width),
|
||
(short) (srcDraw->yOff + src_y + height));
|
||
SetRect(&destRect, (short) (destDraw->xOff + dest_x),
|
||
(short) (destDraw->yOff + dest_y),
|
||
(short) (destDraw->xOff + dest_x + width),
|
||
(short) (destDraw->yOff + dest_y + height));
|
||
tmode = srcCopy;
|
||
|
||
CopyBits(srcBit, destBit, &srcRect, &destRect, tmode, NULL);
|
||
SetGWorld(saveWorld, saveDevice);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XCopyPlane --
|
||
*
|
||
* Copies a bitmap from a source drawable to a destination
|
||
* drawable. The plane argument specifies which bit plane of
|
||
* the source contains the bitmap. Note that this implementation
|
||
* ignores the gc->function.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Changes the destination drawable.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
XCopyPlane(display, src, dest, gc, src_x, src_y,
|
||
width, height, dest_x, dest_y, plane)
|
||
Display* display;
|
||
Drawable src;
|
||
Drawable dest;
|
||
GC gc;
|
||
int src_x;
|
||
int src_y;
|
||
unsigned int width;
|
||
unsigned int height;
|
||
int dest_x;
|
||
int dest_y;
|
||
unsigned long plane;
|
||
{
|
||
Rect srcRect, destRect;
|
||
BitMapPtr srcBit, destBit;
|
||
MacDrawable *srcDraw = (MacDrawable *) src;
|
||
MacDrawable *destDraw = (MacDrawable *) dest;
|
||
GWorldPtr srcPort, destPort;
|
||
CGrafPtr saveWorld;
|
||
GDHandle saveDevice;
|
||
RGBColor macColor;
|
||
short tmode;
|
||
|
||
destPort = TkMacGetDrawablePort(dest);
|
||
srcPort = TkMacGetDrawablePort(src);
|
||
|
||
display->request++;
|
||
GetGWorld(&saveWorld, &saveDevice);
|
||
SetGWorld(destPort, NULL);
|
||
|
||
TkMacSetUpClippingRgn(dest);
|
||
|
||
srcBit = &((GrafPtr) srcPort)->portBits;
|
||
destBit = &((GrafPtr) destPort)->portBits;
|
||
SetRect(&srcRect, (short) (srcDraw->xOff + src_x),
|
||
(short) (srcDraw->yOff + src_y),
|
||
(short) (srcDraw->xOff + src_x + width),
|
||
(short) (srcDraw->yOff + src_y + height));
|
||
SetRect(&destRect, (short) (destDraw->xOff + dest_x),
|
||
(short) (destDraw->yOff + dest_y),
|
||
(short) (destDraw->xOff + dest_x + width),
|
||
(short) (destDraw->yOff + dest_y + height));
|
||
tmode = srcOr;
|
||
|
||
if (TkSetMacColor(gc->foreground, &macColor) == true) {
|
||
RGBForeColor(&macColor);
|
||
}
|
||
|
||
if (TkSetMacColor(gc->background, &macColor) == true) {
|
||
RGBBackColor(&macColor);
|
||
tmode = srcCopy;
|
||
}
|
||
|
||
CopyBits(srcBit, destBit, &srcRect, &destRect, tmode, NULL);
|
||
SetGWorld(saveWorld, saveDevice);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkPutImage --
|
||
*
|
||
* Copies a subimage from an in-memory image to a rectangle of
|
||
* of the specified drawable.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Draws the image on the specified drawable.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
TkPutImage(colors, ncolors, display, d, gc, image, src_x, src_y,
|
||
dest_x, dest_y, width, height)
|
||
unsigned long *colors;
|
||
int ncolors;
|
||
Display* display;
|
||
Drawable d;
|
||
GC gc;
|
||
XImage* image;
|
||
int src_x;
|
||
int src_y;
|
||
int dest_x;
|
||
int dest_y;
|
||
unsigned int width;
|
||
unsigned int height;
|
||
{
|
||
MacDrawable *destDraw = (MacDrawable *) d;
|
||
CGrafPtr saveWorld;
|
||
GDHandle saveDevice;
|
||
GWorldPtr destPort;
|
||
int i, j;
|
||
BitMap bitmap;
|
||
char *newData = NULL;
|
||
Rect destRect, srcRect;
|
||
|
||
destPort = TkMacGetDrawablePort(d);
|
||
SetRect(&destRect, dest_x, dest_y, dest_x + width, dest_y + height);
|
||
SetRect(&srcRect, src_x, src_y, src_x + width, src_y + height);
|
||
|
||
display->request++;
|
||
GetGWorld(&saveWorld, &saveDevice);
|
||
SetGWorld(destPort, NULL);
|
||
|
||
TkMacSetUpClippingRgn(d);
|
||
|
||
if (image->depth == 1) {
|
||
|
||
/*
|
||
* This code assumes a pixel depth of 1
|
||
*/
|
||
|
||
bitmap.bounds.top = bitmap.bounds.left = 0;
|
||
bitmap.bounds.right = (short) image->width;
|
||
bitmap.bounds.bottom = (short) image->height;
|
||
if ((image->bytes_per_line % 2) == 1) {
|
||
char *newPtr, *oldPtr;
|
||
newData = (char *) ckalloc(image->height *
|
||
(image->bytes_per_line + 1));
|
||
newPtr = newData;
|
||
oldPtr = image->data;
|
||
for (i = 0; i < image->height; i++) {
|
||
for (j = 0; j < image->bytes_per_line; j++) {
|
||
*newPtr = InvertByte((unsigned char) *oldPtr);
|
||
newPtr++, oldPtr++;
|
||
}
|
||
*newPtr = 0;
|
||
newPtr++;
|
||
}
|
||
bitmap.baseAddr = newData;
|
||
bitmap.rowBytes = image->bytes_per_line + 1;
|
||
} else {
|
||
newData = (char *) ckalloc(image->height * image->bytes_per_line);
|
||
for (i = 0; i < image->height * image->bytes_per_line; i++) {
|
||
newData[i] = InvertByte((unsigned char) image->data[i]);
|
||
}
|
||
bitmap.baseAddr = newData;
|
||
bitmap.rowBytes = image->bytes_per_line;
|
||
}
|
||
|
||
CopyBits(&bitmap, &((GrafPtr) destPort)->portBits,
|
||
&srcRect, &destRect, srcCopy, NULL);
|
||
|
||
} else {
|
||
/* Color image */
|
||
PixMap pixmap;
|
||
|
||
pixmap.bounds.left = 0;
|
||
pixmap.bounds.top = 0;
|
||
pixmap.bounds.right = (short) image->width;
|
||
pixmap.bounds.bottom = (short) image->height;
|
||
pixmap.pixelType = RGBDirect;
|
||
pixmap.pmVersion = 4; /* 32bit clean */
|
||
pixmap.packType = 0;
|
||
pixmap.packSize = 0;
|
||
pixmap.hRes = 0x00480000;
|
||
pixmap.vRes = 0x00480000;
|
||
pixmap.pixelSize = 32;
|
||
pixmap.cmpCount = 3;
|
||
pixmap.cmpSize = 8;
|
||
pixmap.planeBytes = 0;
|
||
pixmap.pmTable = NULL;
|
||
pixmap.pmReserved = 0;
|
||
pixmap.baseAddr = image->data;
|
||
pixmap.rowBytes = image->bytes_per_line | 0x8000;
|
||
|
||
CopyBits((BitMap *) &pixmap, &((GrafPtr) destPort)->portBits,
|
||
&srcRect, &destRect, srcCopy, NULL);
|
||
}
|
||
|
||
if (newData != NULL) {
|
||
ckfree(newData);
|
||
}
|
||
SetGWorld(saveWorld, saveDevice);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XDrawString --
|
||
*
|
||
* Draw a single string in the current font.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Renders the specified string in the drawable.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
XDrawString(display, d, gc, x, y, string, length)
|
||
Display* display;
|
||
Drawable d;
|
||
GC gc;
|
||
int x;
|
||
int y;
|
||
const char* string;
|
||
int length;
|
||
{
|
||
MacDrawable *macWin = (MacDrawable *) d;
|
||
CGrafPtr saveWorld;
|
||
GWorldPtr destPort;
|
||
BitMapPtr stippleMap;
|
||
GDHandle saveDevice;
|
||
RGBColor macColor;
|
||
short txFont, txFace, txSize;
|
||
short family, style, size;
|
||
|
||
|
||
destPort = TkMacGetDrawablePort(d);
|
||
|
||
display->request++;
|
||
GetGWorld(&saveWorld, &saveDevice);
|
||
SetGWorld(destPort, NULL);
|
||
|
||
TkMacSetUpClippingRgn(d);
|
||
|
||
TkMacSetUpGraphicsPort(gc);
|
||
|
||
TkMacFontInfo(gc->font, &family, &style, &size);
|
||
txFont = qd.thePort->txFont;
|
||
txFace = qd.thePort->txFace;
|
||
txSize = qd.thePort->txSize;
|
||
|
||
if ((gc->fill_style == FillStippled
|
||
|| gc->fill_style == FillOpaqueStippled)
|
||
&& gc->stipple != None) {
|
||
Pixmap pixmap;
|
||
GWorldPtr bufferPort;
|
||
|
||
stippleMap = MakeStippleMap(d, gc->stipple);
|
||
|
||
pixmap = Tk_GetPixmap(display, d,
|
||
stippleMap->bounds.right, stippleMap->bounds.bottom, 0);
|
||
|
||
bufferPort = TkMacGetDrawablePort(pixmap);
|
||
SetGWorld(bufferPort, NULL);
|
||
|
||
TextFont(family);
|
||
TextSize(size);
|
||
TextFace(style);
|
||
|
||
if (TkSetMacColor(gc->foreground, &macColor) == true) {
|
||
RGBForeColor(&macColor);
|
||
}
|
||
|
||
ShowPen();
|
||
MoveTo((short) 0, (short) 0);
|
||
FillRect(&stippleMap->bounds, &qd.white);
|
||
MoveTo((short) x, (short) y);
|
||
DrawText(string, 0, (short) length);
|
||
|
||
destPort = TkMacGetDrawablePort(d);
|
||
SetGWorld(destPort, NULL);
|
||
CopyDeepMask(&((GrafPtr) bufferPort)->portBits, stippleMap,
|
||
&((GrafPtr) destPort)->portBits, &stippleMap->bounds, &stippleMap->bounds,
|
||
&((GrafPtr) destPort)->portRect /* Is this right? */, srcOr, NULL);
|
||
/* TODO: this doesn't work quite right - it does a blend. you can't draw white
|
||
text when you have a stipple.
|
||
*/
|
||
|
||
Tk_FreePixmap(display, pixmap);
|
||
ckfree(stippleMap->baseAddr);
|
||
ckfree((char *)stippleMap);
|
||
} else {
|
||
TextFont(family);
|
||
TextSize(size);
|
||
TextFace(style);
|
||
|
||
if (TkSetMacColor(gc->foreground, &macColor) == true) {
|
||
RGBForeColor(&macColor);
|
||
}
|
||
|
||
ShowPen();
|
||
MoveTo((short) (macWin->xOff + x), (short) (macWin->yOff + y));
|
||
DrawText(string, 0, (short) length);
|
||
}
|
||
|
||
TextFont(txFont);
|
||
TextSize(txSize);
|
||
TextFace(txFace);
|
||
SetGWorld(saveWorld, saveDevice);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XFillRectangles --
|
||
*
|
||
* Fill multiple rectangular areas in the given drawable.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Draws onto the specified drawable.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
XFillRectangles(display, d, gc, rectangles, n_rectangels)
|
||
Display* display;
|
||
Drawable d;
|
||
GC gc;
|
||
XRectangle *rectangles;
|
||
int n_rectangels;
|
||
{
|
||
MacDrawable *macWin = (MacDrawable *) d;
|
||
CGrafPtr saveWorld;
|
||
GDHandle saveDevice;
|
||
GWorldPtr destPort;
|
||
Rect theRect;
|
||
int i;
|
||
|
||
destPort = TkMacGetDrawablePort(d);
|
||
|
||
display->request++;
|
||
GetGWorld(&saveWorld, &saveDevice);
|
||
SetGWorld(destPort, NULL);
|
||
|
||
TkMacSetUpClippingRgn(d);
|
||
|
||
TkMacSetUpGraphicsPort(gc);
|
||
|
||
for (i=0; i<n_rectangels; i++) {
|
||
theRect.left = (short) (macWin->xOff + rectangles[i].x);
|
||
theRect.top = (short) (macWin->yOff + rectangles[i].y);
|
||
theRect.right = (short) (theRect.left + rectangles[i].width);
|
||
theRect.bottom = (short) (theRect.top + rectangles[i].height);
|
||
FillCRect(&theRect, gPenPat);
|
||
}
|
||
|
||
SetGWorld(saveWorld, saveDevice);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XDrawLines --
|
||
*
|
||
* Draw connected lines.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Renders a series of connected lines.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
XDrawLines(display, d, gc, points, npoints, mode)
|
||
Display* display;
|
||
Drawable d;
|
||
GC gc;
|
||
XPoint* points;
|
||
int npoints;
|
||
int mode;
|
||
{
|
||
MacDrawable *macWin = (MacDrawable *) d;
|
||
CGrafPtr saveWorld;
|
||
GWorldPtr destPort;
|
||
GDHandle saveDevice;
|
||
int i;
|
||
|
||
destPort = TkMacGetDrawablePort(d);
|
||
|
||
display->request++;
|
||
if (npoints < 2) {
|
||
return; /* TODO: generate BadValue error. */
|
||
}
|
||
GetGWorld(&saveWorld, &saveDevice);
|
||
SetGWorld(destPort, NULL);
|
||
|
||
TkMacSetUpClippingRgn(d);
|
||
|
||
TkMacSetUpGraphicsPort(gc);
|
||
|
||
ShowPen();
|
||
|
||
PenPixPat(gPenPat);
|
||
MoveTo((short) (macWin->xOff + points[0].x),
|
||
(short) (macWin->yOff + points[0].y));
|
||
for (i = 1; i < npoints; i++) {
|
||
if (mode == CoordModeOrigin) {
|
||
LineTo((short) (macWin->xOff + points[i].x),
|
||
(short) (macWin->yOff + points[i].y));
|
||
} else {
|
||
Line((short) (macWin->xOff + points[i].x),
|
||
(short) (macWin->yOff + points[i].y));
|
||
}
|
||
}
|
||
|
||
SetGWorld(saveWorld, saveDevice);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XFillPolygon --
|
||
*
|
||
* Draws a filled polygon.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Draws a filled polygon on the specified drawable.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
XFillPolygon(display, d, gc, points, npoints, shape, mode)
|
||
Display* display;
|
||
Drawable d;
|
||
GC gc;
|
||
XPoint* points;
|
||
int npoints;
|
||
int shape;
|
||
int mode;
|
||
{
|
||
MacDrawable *macWin = (MacDrawable *) d;
|
||
PolyHandle polygon;
|
||
CGrafPtr saveWorld;
|
||
GDHandle saveDevice;
|
||
GWorldPtr destPort;
|
||
int i;
|
||
|
||
destPort = TkMacGetDrawablePort(d);
|
||
|
||
display->request++;
|
||
GetGWorld(&saveWorld, &saveDevice);
|
||
SetGWorld(destPort, NULL);
|
||
|
||
TkMacSetUpClippingRgn(d);
|
||
|
||
TkMacSetUpGraphicsPort(gc);
|
||
|
||
PenNormal();
|
||
polygon = OpenPoly();
|
||
|
||
MoveTo((short) (macWin->xOff + points[0].x),
|
||
(short) (macWin->yOff + points[0].y));
|
||
for (i = 1; i < npoints; i++) {
|
||
if (mode == CoordModePrevious) {
|
||
Line((short) (macWin->xOff + points[i].x),
|
||
(short) (macWin->yOff + points[i].y));
|
||
} else {
|
||
LineTo((short) (macWin->xOff + points[i].x),
|
||
(short) (macWin->yOff + points[i].y));
|
||
}
|
||
}
|
||
|
||
ClosePoly();
|
||
|
||
FillCPoly(polygon, gPenPat);
|
||
|
||
KillPoly(polygon);
|
||
SetGWorld(saveWorld, saveDevice);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XDrawRectangle --
|
||
*
|
||
* Draws a rectangle.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Draws a rectangle on the specified drawable.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
XDrawRectangle(display, d, gc, x, y, width, height)
|
||
Display* display;
|
||
Drawable d;
|
||
GC gc;
|
||
int x;
|
||
int y;
|
||
unsigned int width;
|
||
unsigned int height;
|
||
{
|
||
MacDrawable *macWin = (MacDrawable *) d;
|
||
Rect theRect;
|
||
CGrafPtr saveWorld;
|
||
GDHandle saveDevice;
|
||
GWorldPtr destPort;
|
||
|
||
destPort = TkMacGetDrawablePort(d);
|
||
|
||
display->request++;
|
||
GetGWorld(&saveWorld, &saveDevice);
|
||
SetGWorld(destPort, NULL);
|
||
|
||
TkMacSetUpClippingRgn(d);
|
||
|
||
TkMacSetUpGraphicsPort(gc);
|
||
|
||
theRect.left = (short) (macWin->xOff + x);
|
||
theRect.top = (short) (macWin->yOff + y);
|
||
theRect.right = (short) (theRect.left + width);
|
||
theRect.bottom = (short) (theRect.top + height);
|
||
|
||
ShowPen();
|
||
PenPixPat(gPenPat);
|
||
FrameRect(&theRect);
|
||
|
||
SetGWorld(saveWorld, saveDevice);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XDrawArc --
|
||
*
|
||
* Draw an arc.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Draws an arc on the specified drawable.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
XDrawArc(display, d, gc, x, y, width, height, angle1, angle2)
|
||
Display* display;
|
||
Drawable d;
|
||
GC gc;
|
||
int x;
|
||
int y;
|
||
unsigned int width;
|
||
unsigned int height;
|
||
int angle1;
|
||
int angle2;
|
||
{
|
||
MacDrawable *macWin = (MacDrawable *) d;
|
||
Rect theRect;
|
||
short start, extent;
|
||
CGrafPtr saveWorld;
|
||
GDHandle saveDevice;
|
||
GWorldPtr destPort;
|
||
|
||
destPort = TkMacGetDrawablePort(d);
|
||
|
||
display->request++;
|
||
GetGWorld(&saveWorld, &saveDevice);
|
||
SetGWorld(destPort, NULL);
|
||
|
||
TkMacSetUpClippingRgn(d);
|
||
|
||
TkMacSetUpGraphicsPort(gc);
|
||
|
||
theRect.left = (short) (macWin->xOff + x);
|
||
theRect.top = (short) (macWin->yOff + y);
|
||
theRect.right = (short) (theRect.left + width);
|
||
theRect.bottom = (short) (theRect.top + height);
|
||
start = (short) (90 - (angle1 / 64));
|
||
extent = (short) (-(angle2 / 64));
|
||
|
||
ShowPen();
|
||
PenPixPat(gPenPat);
|
||
FrameArc(&theRect, start, extent);
|
||
|
||
SetGWorld(saveWorld, saveDevice);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* XFillArc --
|
||
*
|
||
* Draw a filled arc.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Draws a filled arc on the specified drawable.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
XFillArc(display, d, gc, x, y, width, height, angle1, angle2)
|
||
Display* display;
|
||
Drawable d;
|
||
GC gc;
|
||
int x;
|
||
int y;
|
||
unsigned int width;
|
||
unsigned int height;
|
||
int angle1;
|
||
int angle2;
|
||
{
|
||
MacDrawable *macWin = (MacDrawable *) d;
|
||
Rect theRect;
|
||
short start, extent;
|
||
PolyHandle polygon;
|
||
double sin1, cos1, sin2, cos2, angle;
|
||
double boxWidth, boxHeight;
|
||
double vertex[2], center1[2], center2[2];
|
||
CGrafPtr saveWorld;
|
||
GDHandle saveDevice;
|
||
GWorldPtr destPort;
|
||
|
||
destPort = TkMacGetDrawablePort(d);
|
||
|
||
display->request++;
|
||
GetGWorld(&saveWorld, &saveDevice);
|
||
SetGWorld(destPort, NULL);
|
||
|
||
TkMacSetUpClippingRgn(d);
|
||
|
||
TkMacSetUpGraphicsPort(gc);
|
||
|
||
theRect.left = (short) (macWin->xOff + x);
|
||
theRect.top = (short) (macWin->yOff + y);
|
||
theRect.right = (short) (theRect.left + width);
|
||
theRect.bottom = (short) (theRect.top + height);
|
||
start = (short) (90 - (angle1 / 64));
|
||
extent = (short) (- (angle2 / 64));
|
||
|
||
if (gc->arc_mode == ArcChord) {
|
||
boxWidth = theRect.right - theRect.left;
|
||
boxHeight = theRect.bottom - theRect.top;
|
||
angle = -(angle1/64.0)*PI/180.0;
|
||
sin1 = sin(angle);
|
||
cos1 = cos(angle);
|
||
angle -= (angle2/64.0)*PI/180.0;
|
||
sin2 = sin(angle);
|
||
cos2 = cos(angle);
|
||
vertex[0] = (theRect.left + theRect.right)/2.0;
|
||
vertex[1] = (theRect.top + theRect.bottom)/2.0;
|
||
center1[0] = vertex[0] + cos1*boxWidth/2.0;
|
||
center1[1] = vertex[1] + sin1*boxHeight/2.0;
|
||
center2[0] = vertex[0] + cos2*boxWidth/2.0;
|
||
center2[1] = vertex[1] + sin2*boxHeight/2.0;
|
||
|
||
polygon = OpenPoly();
|
||
MoveTo((short) ((theRect.left + theRect.right)/2),
|
||
(short) ((theRect.top + theRect.bottom)/2));
|
||
|
||
LineTo((short) (center1[0] + 0.5), (short) (center1[1] + 0.5));
|
||
LineTo((short) (center2[0] + 0.5), (short) (center2[1] + 0.5));
|
||
ClosePoly();
|
||
|
||
ShowPen();
|
||
FillCArc(&theRect, start, extent, gPenPat);
|
||
FillCPoly(polygon, gPenPat);
|
||
|
||
KillPoly(polygon);
|
||
} else {
|
||
ShowPen();
|
||
FillCArc(&theRect, start, extent, gPenPat);
|
||
}
|
||
|
||
SetGWorld(saveWorld, saveDevice);
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkScrollWindow --
|
||
*
|
||
* Scroll a rectangle of the specified window and accumulate
|
||
* a damage region.
|
||
*
|
||
* Results:
|
||
* Returns 0 if the scroll genereated no additional damage.
|
||
* Otherwise, sets the region that needs to be repainted after
|
||
* scrolling and returns 1.
|
||
*
|
||
* Side effects:
|
||
* Scrolls the bits in the window.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
TkScrollWindow(tkwin, gc, x, y, width, height, dx, dy, damageRgn)
|
||
Tk_Window tkwin; /* The window to be scrolled. */
|
||
GC gc; /* GC for window to be scrolled. */
|
||
int x, y, width, height; /* Position rectangle to be scrolled. */
|
||
int dx, dy; /* Distance rectangle should be moved. */
|
||
TkRegion damageRgn; /* Region to accumulate damage in. */
|
||
{
|
||
MacDrawable *destDraw = (MacDrawable *) Tk_WindowId(tkwin);
|
||
RgnHandle rgn = (RgnHandle) damageRgn;
|
||
CGrafPtr saveWorld;
|
||
GDHandle saveDevice;
|
||
GWorldPtr destPort;
|
||
Rect srcRect, scrollRect;
|
||
|
||
destPort = TkMacGetDrawablePort(Tk_WindowId(tkwin));
|
||
|
||
GetGWorld(&saveWorld, &saveDevice);
|
||
SetGWorld(destPort, NULL);
|
||
|
||
TkMacSetUpClippingRgn(Tk_WindowId(tkwin));
|
||
|
||
/*
|
||
* Due to the implementation below the behavior may be differnt
|
||
* than X in certain cases that should never occur in Tk. The
|
||
* scrollRect is the source rect extended by the offset (the union
|
||
* of the source rect and the offset rect). Everything
|
||
* in the extended scrollRect is scrolled. On X, it's possible
|
||
* to "skip" over an area if the offset makes the source and
|
||
* destination rects disjoint and non-aligned.
|
||
*/
|
||
|
||
SetRect(&srcRect, (short) (destDraw->xOff + x),
|
||
(short) (destDraw->yOff + y),
|
||
(short) (destDraw->xOff + x + width),
|
||
(short) (destDraw->yOff + y + height));
|
||
scrollRect = srcRect;
|
||
if (dx < 0) {
|
||
scrollRect.left += dx;
|
||
} else {
|
||
scrollRect.right += dx;
|
||
}
|
||
if (dy < 0) {
|
||
scrollRect.top += dy;
|
||
} else {
|
||
scrollRect.bottom += dy;
|
||
}
|
||
|
||
/*
|
||
* Adjust clip region so that we don't copy any windows
|
||
* that may overlap us.
|
||
*/
|
||
RectRgn(rgn, &srcRect);
|
||
DiffRgn(rgn, destPort->visRgn, rgn);
|
||
OffsetRgn(rgn, dx, dy);
|
||
DiffRgn(destPort->clipRgn, rgn, destPort->clipRgn);
|
||
|
||
SetEmptyRgn(rgn);
|
||
ScrollRect(&scrollRect, dx, dy, rgn);
|
||
|
||
SetGWorld(saveWorld, saveDevice);
|
||
|
||
/*
|
||
* Fortunantly, the region returned by ScrollRect is symanticlly
|
||
* the same as what we need to return in this function. If the
|
||
* region is empty we return zero to denote that no damage was
|
||
* created.
|
||
*/
|
||
if (EmptyRgn(rgn)) {
|
||
return 0;
|
||
} else {
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkMacSetUpGraphicsPort --
|
||
*
|
||
* Set up the graphics port from the given GC.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* The current port is adjusted.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static void
|
||
TkMacSetUpGraphicsPort(gc)
|
||
GC gc;
|
||
{
|
||
RGBColor macColor;
|
||
|
||
if (gPenPat == NULL) {
|
||
gPenPat = NewPixPat();
|
||
}
|
||
|
||
if (TkSetMacColor(gc->foreground, &macColor) == true) {
|
||
/* TODO: cache RGBPats for preformace - measure gains... */
|
||
MakeRGBPat(gPenPat, &macColor);
|
||
}
|
||
|
||
PenNormal();
|
||
if(gc->function == GXxor) {
|
||
PenMode(patXor);
|
||
}
|
||
if (gc->line_width > 1) {
|
||
PenSize(gc->line_width, gc->line_width);
|
||
}
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkMacSetUpClippingRgn --
|
||
*
|
||
* Set up the clipping region so that drawing only occurs on the
|
||
* specified X subwindow.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* The clipping region in the current port is changed.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
TkMacSetUpClippingRgn(drawable)
|
||
Drawable drawable;
|
||
{
|
||
MacDrawable *macDraw = (MacDrawable *) drawable;
|
||
|
||
if (macDraw->winPtr != NULL) {
|
||
if (macDraw->flags & TK_CLIP_INVALID) {
|
||
TkMacUpdateClipRgn(macDraw->winPtr);
|
||
}
|
||
|
||
if (macDraw->clipRgn != NULL) {
|
||
SetClip(macDraw->clipRgn);
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* MakeStippleMap --
|
||
*
|
||
* Given a drawable and a stipple pattern this function draws the
|
||
* pattern repeatedly over the drawable. The drawable can then
|
||
* be used as a mask for bit-bliting a stipple pattern over an
|
||
* object.
|
||
*
|
||
* Results:
|
||
* A BitMap data structure.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static BitMapPtr
|
||
MakeStippleMap(drawable, stipple)
|
||
Drawable drawable;
|
||
Drawable stipple;
|
||
{
|
||
MacDrawable *destDraw = (MacDrawable *) drawable;
|
||
GWorldPtr destPort;
|
||
BitMapPtr bitmapPtr;
|
||
int width, height, stippleHeight, stippleWidth;
|
||
int i, j;
|
||
char * data;
|
||
Rect bounds;
|
||
|
||
destPort = TkMacGetDrawablePort(drawable);
|
||
width = destPort->portRect.right - destPort->portRect.left;
|
||
height = destPort->portRect.bottom - destPort->portRect.top;
|
||
|
||
bitmapPtr = (BitMap *) ckalloc(sizeof(BitMap));
|
||
data = (char *) ckalloc(height * ((width / 8) + 1));
|
||
bitmapPtr->bounds.top = bitmapPtr->bounds.left = 0;
|
||
bitmapPtr->bounds.right = (short) width;
|
||
bitmapPtr->bounds.bottom = (short) height;
|
||
bitmapPtr->baseAddr = data;
|
||
bitmapPtr->rowBytes = (width / 8) + 1;
|
||
|
||
destPort = TkMacGetDrawablePort(stipple);
|
||
stippleWidth = destPort->portRect.right - destPort->portRect.left;
|
||
stippleHeight = destPort->portRect.bottom - destPort->portRect.top;
|
||
|
||
for (i = 0; i < height; i += stippleHeight) {
|
||
for (j = 0; j < width; j += stippleWidth) {
|
||
bounds.left = j;
|
||
bounds.top = i;
|
||
bounds.right = j + stippleWidth;
|
||
bounds.bottom = i + stippleHeight;
|
||
|
||
CopyBits(&((GrafPtr) destPort)->portBits, bitmapPtr,
|
||
&((GrafPtr) destPort)->portRect, &bounds, srcCopy, NULL);
|
||
}
|
||
}
|
||
return bitmapPtr;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* InvertByte --
|
||
*
|
||
* This function reverses the bits in the passed in Byte of data.
|
||
*
|
||
* Results:
|
||
* The incoming byte in reverse bit order.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static unsigned char
|
||
InvertByte(unsigned char data)
|
||
{
|
||
unsigned char i;
|
||
unsigned char mask = 1, result = 0;
|
||
|
||
for (i = (1 << 7); i != 0; i /= 2) {
|
||
if (data & mask) {
|
||
result |= i;
|
||
}
|
||
mask = mask << 1;
|
||
}
|
||
return result;
|
||
}
|