Quartz for FLTK 1.1:

- added pixmap drawing (no masking yet)
- added bitmap drawing
- added line styles (complete)
todo:
- missing refresh (double test, fluid, others)
- missing pixmap mask
- color_chooser has alignment issues
- images scale instead of beeing scissored
- fonts


git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@3798 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Matthias Melcher 2004-08-31 00:27:40 +00:00
parent 62e1ae6976
commit 57193e52c0
9 changed files with 215 additions and 183 deletions

View File

@ -1,5 +1,5 @@
//
// "$Id: mac.H,v 1.1.2.13 2004/08/27 20:02:43 matthiaswm Exp $"
// "$Id: mac.H,v 1.1.2.14 2004/08/31 00:27:40 matthiaswm Exp $"
//
// Mac header file for the Fast Light Tool Kit (FLTK).
//
@ -82,6 +82,8 @@ public:
static void q_fill_context(); // fill a Quartz context with current FLTK state
static void q_clear_clipping(); // remove all clipping from a Quartz context
static void q_release_context(Fl_X *x=0); // free all resources associated with fl_gc
static void q_begin_image(CGRect&, int x, int y);
static void q_end_image();
};
inline Window fl_xid(const Fl_Window*w)
@ -124,6 +126,6 @@ extern void fl_open_callback(void (*cb)(const char *));
extern FL_EXPORT int fl_parse_color(const char* p, uchar& r, uchar& g, uchar& b);
//
// End of "$Id: mac.H,v 1.1.2.13 2004/08/27 20:02:43 matthiaswm Exp $".
// End of "$Id: mac.H,v 1.1.2.14 2004/08/31 00:27:40 matthiaswm Exp $".
//

View File

@ -1,5 +1,5 @@
//
// "$Id: Fl_Bitmap.cxx,v 1.5.2.4.2.24 2004/08/25 00:20:25 matthiaswm Exp $"
// "$Id: Fl_Bitmap.cxx,v 1.5.2.4.2.25 2004/08/31 00:27:40 matthiaswm Exp $"
//
// Bitmap drawing routines for the Fast Light Tool Kit (FLTK).
//
@ -78,49 +78,23 @@ void fl_delete_bitmask(Fl_Bitmask id) {
if (id) DisposeGWorld(id);
}
#elif defined(__APPLE_QUARTZ__)
# warning quartz
Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *array) {
Rect srcRect;
srcRect.left = 0; srcRect.right = w;
srcRect.top = 0; srcRect.bottom = h;
GrafPtr savePort;
GetPort(&savePort); // remember the current port
Fl_Bitmask gw;
NewGWorld( &gw, 1, &srcRect, 0L, 0L, 0 );
PixMapHandle pm = GetGWorldPixMap( gw );
if ( pm )
{
LockPixels( pm );
if ( *pm )
{
uchar *base = (uchar*)GetPixBaseAddr( pm );
if ( base )
{
PixMapPtr pmp = *pm;
// verify the parameters for direct memory write
if ( pmp->pixelType == 0 || pmp->pixelSize == 1 || pmp->cmpCount == 1 || pmp->cmpSize == 1 )
{
static uchar reverse[16] = /* Bit reversal lookup table */
{ 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee, 0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff };
uchar *dst = base;
const uchar *src = array;
int rowBytesSrc = (w+7)>>3 ;
int rowPatch = (pmp->rowBytes&0x3fff) - rowBytesSrc;
for ( int j=0; j<h; j++,dst+=rowPatch )
for ( int i=0; i<rowBytesSrc; i++,src++ )
*dst++ = (reverse[*src & 0x0f] & 0xf0) | (reverse[(*src >> 4) & 0x0f] & 0x0f);
}
}
UnlockPixels( pm );
}
static uchar reverse[16] = /* Bit reversal lookup table */
{ 0x00, 0x88, 0x44, 0xcc, 0x22, 0xaa, 0x66, 0xee,
0x11, 0x99, 0x55, 0xdd, 0x33, 0xbb, 0x77, 0xff };
int rowBytes = (w+7)>>3 ;
uchar *bmask = (uchar*)malloc(rowBytes*h), *dst = bmask;
const uchar *src = array;
for ( int i=rowBytes*h; i>0; i--,src++ ) {
*dst++ = ((reverse[*src & 0x0f] & 0xf0) | (reverse[(*src >> 4) & 0x0f] & 0x0f))^0xff;
}
SetPort(savePort);
return gw; /* tell caller we succeeded! */
CGDataProviderRef srcp = CGDataProviderCreateWithData( 0L, bmask, rowBytes*h, 0L);
CGImageRef id = CGImageMaskCreate( w, h, 1, 1, rowBytes, srcp, 0L, false);
CGDataProviderRelease(srcp);
return (Fl_Bitmask)id;
}
void fl_delete_bitmask(Fl_Bitmask id) {
if (id) DisposeGWorld(id);
if (id) CGImageRelease((CGImageRef)id);
}
#elif defined(WIN32) // Windows bitmask functions...
// 'fl_create_bitmap()' - Create a 1-bit bitmap for drawing...
@ -416,20 +390,13 @@ void Fl_Bitmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) {
srcOr, // mode
0L); // mask region
#elif defined(__APPLE_QUARTZ__)
# warning quartz
if (!id) id = fl_create_bitmask(w(), h(), array);
GrafPtr dstPort;
GetPort( &dstPort );
Rect src, dst;
GetPortBounds( (Fl_Offscreen)id, &src );
SetRect( &src, cx, cy, cx+W, cy+H );
SetRect( &dst, X, Y, X+W, Y+H );
CopyBits(GetPortBitMapForCopyBits((Fl_Offscreen)id), // srcBits
GetPortBitMapForCopyBits(dstPort), // dstBits
&src, // src bounds
&dst, // dst bounds
srcOr, // mode
0L); // mask region
if (id && fl_gc) {
CGRect rect = { X, Y, W, H };
Fl_X::q_begin_image(rect, cx, cy);
CGContextDrawImage(fl_gc, rect, (CGImageRef)id);
Fl_X::q_end_image();
}
#else
if (!id) id = fl_create_bitmask(w(), h(), array);
@ -534,5 +501,5 @@ Fl_Image *Fl_Bitmap::copy(int W, int H) {
//
// End of "$Id: Fl_Bitmap.cxx,v 1.5.2.4.2.24 2004/08/25 00:20:25 matthiaswm Exp $".
// End of "$Id: Fl_Bitmap.cxx,v 1.5.2.4.2.25 2004/08/31 00:27:40 matthiaswm Exp $".
//

View File

@ -1,5 +1,5 @@
//
// "$Id: Fl_Double_Window.cxx,v 1.12.2.4.2.10 2004/08/25 00:20:25 matthiaswm Exp $"
// "$Id: Fl_Double_Window.cxx,v 1.12.2.4.2.11 2004/08/31 00:27:40 matthiaswm Exp $"
//
// Double-buffered window code for the Fast Light Tool Kit (FLTK).
//
@ -164,70 +164,62 @@ void fl_end_offscreen() {
extern void fl_restore_clip();
#elif defined(__APPLE_QUARTZ__)
#warning quartz
GWorldPtr fl_create_offscreen(int w, int h) {
GWorldPtr gw;
Rect bounds;
bounds.left=0; bounds.right=w; bounds.top=0; bounds.bottom=h;
QDErr err = NewGWorld(&gw, 0, &bounds, 0L, 0L, 0); // 'useTempMem' should not be used (says the Carbon port manual)
if ( err == -108 )
{ }
// fl_message( "The application memory is low. Please increase the initial memory assignment.\n" );
if (err!=noErr || gw==0L) return 0L;
return gw;
Fl_Offscreen fl_create_offscreen(int w, int h) {
void *data = malloc(w*h*4);
CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(
data, w, h, 8, w*4, lut, kCGImageAlphaNoneSkipLast);
CGColorSpaceRelease(lut);
return (Fl_Offscreen)ctx;
}
void fl_copy_offscreen(int x,int y,int w,int h,GWorldPtr gWorld,int srcx,int srcy) {
Rect src;
if ( !gWorld ) return;
src.top = srcy; src.left = srcx; src.bottom = srcy+h; src.right = srcx+w;
Rect dst;
GrafPtr dstPort; GetPort(&dstPort);
dst.top = y; dst.left = x; dst.bottom = y+h; dst.right = x+w;
RGBColor rgb;
rgb.red = 0xffff; rgb.green = 0xffff; rgb.blue = 0xffff;
RGBBackColor( &rgb );
rgb.red = 0x0000; rgb.green = 0x0000; rgb.blue = 0x0000;
RGBForeColor( &rgb );
CopyBits(GetPortBitMapForCopyBits(gWorld), GetPortBitMapForCopyBits(dstPort), &src, &dst, srcCopy, 0L);
void fl_copy_offscreen(int x,int y,int w,int h,Fl_Offscreen osrc,int srcx,int srcy) {
#warning : test this implementation!
CGContextRef src = (CGContextRef)osrc;
void *data = CGBitmapContextGetData(src);
int sw = CGBitmapContextGetWidth(src);
int sh = CGBitmapContextGetHeight(src);
CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB();
CGDataProviderRef src_bytes = CGDataProviderCreateWithData( 0L, data, sw*sh*4, 0L);
CGImageRef img = CGImageCreate( sw, sh, 8, 4*8, 4*sw, lut, kCGImageAlphaNoneSkipLast,
src_bytes, 0L, false, kCGRenderingIntentDefault);
// fl_push_clip();
CGRect rect = { x, y, w, h };
Fl_X::q_begin_image(rect, srcx, srcy);
CGContextDrawImage(fl_gc, rect, img);
Fl_X::q_end_image();
CGImageRelease(img);
CGColorSpaceRelease(lut);
CGDataProviderRelease(src_bytes);
}
void fl_delete_offscreen(GWorldPtr gWorld) {
DisposeGWorld(gWorld);
void fl_delete_offscreen(Fl_Offscreen ctx) {
if (!ctx) return;
void *data = CGBitmapContextGetData((CGContextRef)ctx);
CGContextRelease((CGContextRef)ctx);
if (!data) return;
free(data);
}
static GrafPtr prevPort;
static GDHandle prevGD;
static CGContextRef prev_gc = 0;
static Window prev_window = 0;
void fl_begin_offscreen(GWorldPtr gWorld) {
GetGWorld( &prevPort, &prevGD );
if ( gWorld )
{
SetGWorld( gWorld, 0 ); // sets the correct port
PixMapHandle pm = GetGWorldPixMap(gWorld);
Boolean ret = LockPixels(pm);
if ( ret == false )
{
Rect rect;
GetPortBounds( gWorld, &rect );
UpdateGWorld( &gWorld, 0, &rect, 0, 0, 0 );
pm = GetGWorldPixMap( gWorld );
LockPixels( pm );
}
fl_window = 0;
}
fl_push_no_clip();
void fl_begin_offscreen(Fl_Offscreen ctx) {
prev_gc = fl_gc;
prev_window = fl_window;
fl_gc = (CGContextRef)ctx;
fl_window = 0;
//fl_push_no_clip();
CGContextSaveGState(fl_gc);
Fl_X::q_fill_context();
}
void fl_end_offscreen() {
GWorldPtr currPort;
GDHandle currGD;
GetGWorld( &currPort, &currGD );
fl_pop_clip();
PixMapHandle pm = GetGWorldPixMap(currPort);
UnlockPixels(pm);
SetGWorld( prevPort, prevGD );
fl_window = GetWindowFromPort( prevPort );
Fl_X::q_release_context();
//fl_pop_clip();
fl_gc = prev_gc;
fl_window = prev_window;
}
extern void fl_restore_clip();
@ -375,5 +367,5 @@ Fl_Double_Window::~Fl_Double_Window() {
}
//
// End of "$Id: Fl_Double_Window.cxx,v 1.12.2.4.2.10 2004/08/25 00:20:25 matthiaswm Exp $".
// End of "$Id: Fl_Double_Window.cxx,v 1.12.2.4.2.11 2004/08/31 00:27:40 matthiaswm Exp $".
//

View File

@ -1,5 +1,5 @@
//
// "$Id: Fl_Image.cxx,v 1.5.2.3.2.35 2004/08/28 13:45:27 easysw Exp $"
// "$Id: Fl_Image.cxx,v 1.5.2.3.2.36 2004/08/31 00:27:40 matthiaswm Exp $"
//
// Image drawing code for the Fast Light Tool Kit (FLTK).
//
@ -327,7 +327,6 @@ void Fl_RGB_Image::draw(int XP, int YP, int WP, int HP, int cx, int cy) {
fl_begin_offscreen((Fl_Offscreen)id);
fl_draw_image(array, 0, 0, w(), h(), d(), ld());
fl_end_offscreen();
if (d() == 2 || d() == 4) {
mask = fl_create_alphamask(w(), h(), d(), ld(), array);
}
@ -380,10 +379,11 @@ void Fl_RGB_Image::draw(int XP, int YP, int WP, int HP, int cx, int cy) {
fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id, cx, cy);
}
#elif defined(__APPLE_QUARTZ__)
# warning : Quartz implementation not finished yet
if (id && fl_gc) {
CGRect rect = { X, Y, w(), h() };
CGRect rect = { X, Y, W, H };
Fl_X::q_begin_image(rect, cx, cy);
CGContextDrawImage(fl_gc, rect, (CGImageRef)id);
Fl_X::q_end_image();
}
#else
if (mask) {
@ -418,5 +418,5 @@ void Fl_RGB_Image::label(Fl_Menu_Item* m) {
//
// End of "$Id: Fl_Image.cxx,v 1.5.2.3.2.35 2004/08/28 13:45:27 easysw Exp $".
// End of "$Id: Fl_Image.cxx,v 1.5.2.3.2.36 2004/08/31 00:27:40 matthiaswm Exp $".
//

View File

@ -1,5 +1,5 @@
//
// "$Id: Fl_Pixmap.cxx,v 1.9.2.4.2.29 2004/08/25 00:20:25 matthiaswm Exp $"
// "$Id: Fl_Pixmap.cxx,v 1.9.2.4.2.30 2004/08/31 00:27:40 matthiaswm Exp $"
//
// Pixmap drawing code for the Fast Light Tool Kit (FLTK).
//
@ -80,6 +80,7 @@ void Fl_Pixmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) {
if (cy+H > h()) H = h()-cy;
if (H <= 0) return;
if (!id) {
#warning : to enable masking in Quartz, write our own version of this little function!
id = fl_create_offscreen(w(), h());
fl_begin_offscreen((Fl_Offscreen)id);
uchar *bitmap = 0;
@ -124,25 +125,7 @@ void Fl_Pixmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) {
fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id, cx, cy);
}
#elif defined(__APPLE_QUARTZ__)
#warning quartz
if (mask) {
Rect src, dst;
src.left = cx; src.right = cx+W;
src.top = cy; src.bottom = cy+H;
dst.left = X; dst.right = X+W;
dst.top = Y; dst.bottom = Y+H;
RGBColor rgb;
rgb.red = 0xffff; rgb.green = 0xffff; rgb.blue = 0xffff;
RGBBackColor(&rgb);
rgb.red = 0x0000; rgb.green = 0x0000; rgb.blue = 0x0000;
RGBForeColor(&rgb);
CopyMask(GetPortBitMapForCopyBits((GrafPtr)id),
GetPortBitMapForCopyBits((GrafPtr)mask),
GetPortBitMapForCopyBits(GetWindowPort(fl_window)),
&src, &src, &dst);
} else {
fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id, cx, cy);
}
fl_copy_offscreen(X, Y, W, H, (Fl_Offscreen)id, cx, cy);
#else
if (mask) {
// I can't figure out how to combine a mask with existing region,
@ -481,5 +464,5 @@ void Fl_Pixmap::desaturate() {
}
//
// End of "$Id: Fl_Pixmap.cxx,v 1.9.2.4.2.29 2004/08/25 00:20:25 matthiaswm Exp $".
// End of "$Id: Fl_Pixmap.cxx,v 1.9.2.4.2.30 2004/08/31 00:27:40 matthiaswm Exp $".
//

View File

@ -1,5 +1,5 @@
//
// "$Id: Fl_mac.cxx,v 1.1.2.61 2004/08/27 20:02:44 matthiaswm Exp $"
// "$Id: Fl_mac.cxx,v 1.1.2.62 2004/08/31 00:27:40 matthiaswm Exp $"
//
// MacOS specific code for the Fast Light Tool Kit (FLTK).
//
@ -1859,29 +1859,10 @@ void Fl_Window::make_current()
SetPortClipRegion( GetWindowPort(i->xid), fl_window_region );
#ifdef __APPLE_QUARTZ__
#warning : bracket all the QD stuff above with ifdefs!
#warning : verbose copy of patch; please check code
#if 0
Rect portRect;
GetPortBounds(GetWindowPort(i->xid), &portRect);
short port_height = portRect.bottom - portRect.top;
if (!i->gc) {
//CreateCGContextForPort(GetWindowPort(i->xid), &i->gc);
QDBeginCGContext(GetWindowPort(i->xid), &i->gc);
// save the unclipped state for later
CGContextSaveGState(i->gc);
// translate coordinate system to coorespond with fltk's.
CGContextTranslateCTM(i->gc, 0.5f, port_height-0.5f);
CGContextScaleCTM(i->gc, 1.0f, -1.0f);
static CGAffineTransform font_mx = { 1, 0, 0, -1, 0, 0 };
CGContextSetTextMatrix(i->gc, font_mx);
}
fl_gc = i->gc;
#else
QDBeginCGContext(GetWindowPort(i->xid), &i->gc);
fl_gc = i->gc;
CGContextSaveGState(fl_gc);
Fl_X::q_fill_context();
#endif
#endif
return;
}
@ -1891,19 +1872,27 @@ void Fl_Window::make_current()
extern Fl_Color fl_color_;
extern class Fl_FontSize *fl_fontsize;
extern void fl_font(class Fl_FontSize*);
extern void fl_quartz_restore_line_style_();
// FLTK has only on global graphics state. This function copies the FLTK state into the
// current Quartz context
void Fl_X::q_fill_context() {
if (!fl_gc) return;
Rect portRect;
GetPortBounds(GetWindowPort( fl_window ), &portRect);
CGContextTranslateCTM(fl_gc, 0.5, portRect.bottom-portRect.top-0.5f);
int hgt = 0;
if (fl_window) {
Rect portRect;
GetPortBounds(GetWindowPort( fl_window ), &portRect);
hgt = portRect.bottom-portRect.top;
} else {
hgt = CGBitmapContextGetHeight(fl_gc);
}
CGContextTranslateCTM(fl_gc, 0.5, hgt-0.5f);
CGContextScaleCTM(fl_gc, 1.0f, -1.0f);
static CGAffineTransform font_mx = { 1, 0, 0, -1, 0, 0 };
CGContextSetTextMatrix(fl_gc, font_mx);
fl_font(fl_fontsize);
fl_color(fl_color_);
fl_quartz_restore_line_style_();
}
// The only way to reste clipping to its original state is to pop the current graphics
@ -1919,10 +1908,25 @@ void Fl_X::q_release_context(Fl_X *x) {
if (x && x->gc!=fl_gc) return;
if (!fl_gc) return;
CGContextRestoreGState(fl_gc);
QDEndCGContext(GetWindowPort(fl_window), &fl_gc);
if (fl_window) QDEndCGContext(GetWindowPort(fl_window), &fl_gc);
fl_gc = 0;
}
void Fl_X::q_begin_image(CGRect &rect, int cx, int cy) {
CGContextSaveGState(fl_gc);
CGAffineTransform mx = CGContextGetCTM(fl_gc);
mx.d = -1.0;
CGContextConcatCTM(fl_gc, mx);
rect.origin.y = (mx.ty-0.5f) - rect.origin.y - rect.size.height + 1;
#warning : quartz - this needs to be fixed!
// this version will scale images into some position. Instead, it should clip them!
// we probably need the image size as an additional argument!
}
void Fl_X::q_end_image() {
CGContextRestoreGState(fl_gc);
}
#endif
////////////////////////////////////////////////////////////////
@ -1997,6 +2001,6 @@ void Fl::paste(Fl_Widget &receiver, int clipboard) {
//
// End of "$Id: Fl_mac.cxx,v 1.1.2.61 2004/08/27 20:02:44 matthiaswm Exp $".
// End of "$Id: Fl_mac.cxx,v 1.1.2.62 2004/08/31 00:27:40 matthiaswm Exp $".
//

View File

@ -1,5 +1,5 @@
//
// "$Id: fl_draw_image_mac.cxx,v 1.1.2.7 2004/08/25 00:20:27 matthiaswm Exp $"
// "$Id: fl_draw_image_mac.cxx,v 1.1.2.8 2004/08/31 00:27:40 matthiaswm Exp $"
//
// MacOS image drawing code for the Fast Light Tool Kit (FLTK).
//
@ -58,6 +58,7 @@ static void innards(const uchar *buf, int X, int Y, int W, int H,
{
if (!linedelta) linedelta = W*delta;
#ifdef __APPLE_QD__
// theoretically, if the current GPort permits, we could write
// directly into it, avoiding the temporary GWorld. For now I
// will go the safe way... .
@ -167,7 +168,51 @@ static void innards(const uchar *buf, int X, int Y, int W, int H,
}
}
}
#elif defined(__APPLE_QUARTZ__)
// following the very save (and very slow) way to write the image into the give port
CGContextSetShouldAntialias(fl_gc, false);
if ( cb )
{
uchar *tmpBuf = new uchar[ W*4 ];
for ( int i=0; i<H; i++ )
{
uchar *src = tmpBuf;
cb( userdata, 0, i, W, tmpBuf );
for ( int j=0; j<W; j++ )
{
if ( mono )
{ fl_color( src[0], src[0], src[0] ); src++; }
else
{ fl_color( src[0], src[1], src[2] ); src+=4; }
CGContextMoveToPoint(fl_gc, X+j, Y+i);
CGContextAddLineToPoint(fl_gc, X+j, Y+i);
CGContextStrokePath(fl_gc);
}
}
delete[] tmpBuf;
}
else
{
for ( int i=0; i<H; i++ )
{
const uchar *src = buf+i*linedelta;
for ( int j=0; j<W; j++ )
{
if ( mono )
fl_color( src[0], src[0], src[0] );
else
fl_color( src[0], src[1], src[2] );
CGContextMoveToPoint(fl_gc, X+j, Y+i);
CGContextAddLineToPoint(fl_gc, X+j, Y+i);
CGContextStrokePath(fl_gc);
src += delta;
}
}
}
CGContextSetShouldAntialias(fl_gc, true);
#else
# error : you must defined __APPLE_QD__ or __APPLE_QUARTZ__
#endif
// \todo Mac : the above function does not support subregions yet
#ifdef later_we_do_this
// \todo Mac : the following code is taken from fl_draw_image_win32 and needs to be modified for Mac Carbon
@ -279,5 +324,5 @@ void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
}
//
// End of "$Id: fl_draw_image_mac.cxx,v 1.1.2.7 2004/08/25 00:20:27 matthiaswm Exp $".
// End of "$Id: fl_draw_image_mac.cxx,v 1.1.2.8 2004/08/31 00:27:40 matthiaswm Exp $".
//

View File

@ -1,5 +1,5 @@
//
// "$Id: fl_line_style.cxx,v 1.3.2.3.2.15 2004/08/25 00:20:27 matthiaswm Exp $"
// "$Id: fl_line_style.cxx,v 1.3.2.3.2.16 2004/08/31 00:27:40 matthiaswm Exp $"
//
// Line style code for the Fast Light Tool Kit (FLTK).
//
@ -29,6 +29,20 @@
#include "flstring.h"
#include <stdio.h>
#ifdef __APPLE_QUARTZ__
static float fl_quartz_line_width_ = 1.0f;
static enum CGLineCap fl_quartz_line_cap_ = kCGLineCapButt;
static enum CGLineJoin fl_quartz_line_join_ = kCGLineJoinMiter;
static float *fl_quartz_line_pattern = 0;
static int fl_quartz_line_pattern_size = 0;
void fl_quartz_restore_line_style_() {
CGContextSetLineWidth(fl_gc, fl_quartz_line_width_);
CGContextSetLineCap(fl_gc, fl_quartz_line_cap_);
CGContextSetLineJoin(fl_gc, fl_quartz_line_join_);
CGContextSetLineDash(fl_gc, 0, fl_quartz_line_pattern, fl_quartz_line_pattern_size);
}
#endif
void fl_line_style(int style, int width, char* dashes) {
#ifdef WIN32
// According to Bill, the "default" cap and join should be the
@ -69,20 +83,45 @@ void fl_line_style(int style, int width, char* dashes) {
if (style > 2) style = 2;
PenPat(styles + style);
#elif defined(__APPLE_QUARTZ__)
#warning quartz
// QuickDraw supports pen size and pattern, but no arbitrary line styles.
static Pattern styles[] = {
{ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }, // FL_SOLID
{ { 0xf0, 0xf0, 0xf0, 0xf0, 0x0f, 0x0f, 0x0f, 0x0f } }, // FL_DASH
{ { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 } } // FL_DOT
};
if (!width) width = 1;
PenSize(width, width);
style &= 0xff;
if (style > 2) style = 2;
PenPat(styles + style);
static enum CGLineCap Cap[4] = { kCGLineCapButt, kCGLineCapButt,
kCGLineCapRound, kCGLineCapSquare };
static enum CGLineJoin Join[4] = { kCGLineJoinMiter, kCGLineJoinMiter,
kCGLineJoinRound, kCGLineJoinBevel };
if (width<1) width = 1;
fl_quartz_line_width_ = (float)width;
fl_quartz_line_cap_ = Cap[(style>>8)&3];
fl_quartz_line_join_ = Join[(style>>12)&3];
char *d = dashes;
static float pattern[16];
if (d && *d) {
float *p = pattern;
while (*d) { *p++ = (float)*d++; }
fl_quartz_line_pattern = pattern;
fl_quartz_line_pattern_size = d-dashes;
} else if (style & 0xff) {
char dash, dot, gap;
// adjust lengths to account for cap:
if (style & 0x200) {
dash = char(2*width);
dot = 1;
gap = char(2*width-1);
} else {
dash = char(3*width);
dot = gap = char(width);
}
float *p = pattern;
switch (style & 0xff) {
case FL_DASH: *p++ = dash; *p++ = gap; break;
case FL_DOT: *p++ = dot; *p++ = gap; break;
case FL_DASHDOT: *p++ = dash; *p++ = gap; *p++ = dot; *p++ = gap; break;
case FL_DASHDOTDOT: *p++ = dash; *p++ = gap; *p++ = dot; *p++ = gap; *p++ = dot; *p++ = gap; break;
}
fl_quartz_line_pattern_size = p-pattern;
fl_quartz_line_pattern = pattern;
} else {
fl_quartz_line_pattern = 0; fl_quartz_line_pattern_size = 0;
}
fl_quartz_restore_line_style_();
#else
int ndashes = dashes ? strlen(dashes) : 0;
// emulate the WIN32 dash patterns on X
@ -119,5 +158,5 @@ void fl_line_style(int style, int width, char* dashes) {
//
// End of "$Id: fl_line_style.cxx,v 1.3.2.3.2.15 2004/08/25 00:20:27 matthiaswm Exp $".
// End of "$Id: fl_line_style.cxx,v 1.3.2.3.2.16 2004/08/31 00:27:40 matthiaswm Exp $".
//

View File

@ -48,7 +48,7 @@
@u:navigation:navigation
@u:minimum update:minimum
@u:keyboard:keyboard
@u:fast & slow widgets:fast_slow
@u:fast && slow widgets:fast_slow
@u:inactive:inactive
@main:Fluid\n(UI design tool):../fluid/fluid valuators.fl