finished implementation for stencil and colored patterns
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@36092 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -304,208 +304,189 @@ void wxMacCGContext::SetNativeContext( CGContextRef cg )
|
|||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
// Experimental support for dashes and patterned brushes
|
// wrapper class for a CGPattern, always allocate on heap, never call destructor
|
||||||
// uncomment the following lines to enable it
|
|
||||||
|
|
||||||
// #define _NEW_GC_DASHES_
|
class wxMacCGPattern
|
||||||
// #define _NEW_GC_SUPPORT_
|
{
|
||||||
|
public :
|
||||||
|
wxMacCGPattern()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4
|
// is guaranteed to be called only with a non-Null CGContextRef
|
||||||
#define kCGColorSpaceGenericRGB CFSTR("kCGColorSpaceGenericRGB")
|
virtual void Render( CGContextRef ctxRef ) = 0 ;
|
||||||
|
|
||||||
|
operator CGPatternRef() const { return m_patternRef ; }
|
||||||
|
protected :
|
||||||
|
virtual ~wxMacCGPattern()
|
||||||
|
{
|
||||||
|
// as this is called only when our m_patternRef is been released, don't release
|
||||||
|
// it again
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _Render( void *info, CGContextRef ctxRef )
|
||||||
|
{
|
||||||
|
wxMacCGPattern* self = (wxMacCGPattern*) info ;
|
||||||
|
if ( self && ctxRef )
|
||||||
|
self->Render( ctxRef ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _Dispose( void *info )
|
||||||
|
{
|
||||||
|
wxMacCGPattern* self = (wxMacCGPattern*) info ;
|
||||||
|
delete self ;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGPatternRef m_patternRef ;
|
||||||
|
|
||||||
|
static const CGPatternCallbacks ms_Callbacks ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
const CGPatternCallbacks wxMacCGPattern::ms_Callbacks = { 0, &wxMacCGPattern::_Render, &wxMacCGPattern::_Dispose };
|
||||||
|
|
||||||
|
class ImagePattern : public wxMacCGPattern
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
ImagePattern( const wxBitmap* bmp , CGAffineTransform transform )
|
||||||
|
{
|
||||||
|
wxASSERT( bmp && bmp->Ok() ) ;
|
||||||
|
Init( (CGImageRef) bmp->CGImageCreate() , transform ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImagePattern takes ownership of CGImageRef passed in
|
||||||
|
ImagePattern( CGImageRef image , CGAffineTransform transform )
|
||||||
|
{
|
||||||
|
if ( image )
|
||||||
|
{
|
||||||
|
CFRetain( image ) ;
|
||||||
|
}
|
||||||
|
Init( image , transform ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Render( CGContextRef ctxRef )
|
||||||
|
{
|
||||||
|
if (m_image != NULL)
|
||||||
|
HIViewDrawCGImage( ctxRef, &m_imageBounds, m_image );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected :
|
||||||
|
void Init( CGImageRef image , CGAffineTransform transform )
|
||||||
|
{
|
||||||
|
m_image = image ;
|
||||||
|
if ( m_image )
|
||||||
|
{
|
||||||
|
m_imageBounds = CGRectMake( 0.0, 0.0, (float)CGImageGetWidth( m_image ), (float)CGImageGetHeight( m_image ) ) ;
|
||||||
|
m_patternRef = CGPatternCreate( this , m_imageBounds, transform ,
|
||||||
|
m_imageBounds.size.width, m_imageBounds.size.height,
|
||||||
|
kCGPatternTilingNoDistortion, true , &wxMacCGPattern::ms_Callbacks ) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~ImagePattern()
|
||||||
|
{
|
||||||
|
if ( m_image )
|
||||||
|
CGImageRelease( m_image ) ;
|
||||||
|
}
|
||||||
|
CGImageRef m_image ;
|
||||||
|
CGRect m_imageBounds ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
class HatchPattern : public wxMacCGPattern
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
HatchPattern( int hatchstyle , CGAffineTransform transform )
|
||||||
|
{
|
||||||
|
m_hatch = hatchstyle ;
|
||||||
|
m_imageBounds = CGRectMake( 0.0, 0.0, 8.0 , 8.0 ) ;
|
||||||
|
m_patternRef = CGPatternCreate( this , m_imageBounds, transform ,
|
||||||
|
m_imageBounds.size.width, m_imageBounds.size.height,
|
||||||
|
kCGPatternTilingNoDistortion, false , &wxMacCGPattern::ms_Callbacks ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StrokeLineSegments( CGContextRef ctxRef , const CGPoint pts[] , size_t count )
|
||||||
|
{
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
|
||||||
|
if ( UMAGetSystemVersion() >= 0x1040 )
|
||||||
|
{
|
||||||
|
CGContextStrokeLineSegments( ctxRef , pts , count ) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void EstablishPatternColorSpace(
|
|
||||||
CGContextRef ctxRef,
|
|
||||||
bool useMultibit,
|
|
||||||
bool useFill )
|
|
||||||
{
|
|
||||||
CGColorSpaceRef baseSpace, patternSpace;
|
|
||||||
|
|
||||||
if (ctxRef == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
baseSpace = NULL;
|
|
||||||
patternSpace = NULL;
|
|
||||||
|
|
||||||
if (useMultibit)
|
|
||||||
{
|
{
|
||||||
patternSpace = CGColorSpaceCreatePattern( NULL );
|
CGContextBeginPath (ctxRef);
|
||||||
|
for (size_t i = 0; i < count; i += 2) {
|
||||||
if (useFill)
|
CGContextMoveToPoint(ctxRef, pts[i].x, pts[i].y);
|
||||||
CGContextSetFillColorSpace( ctxRef, patternSpace );
|
CGContextAddLineToPoint(ctxRef, pts[i+1].x, pts[i+1].y);
|
||||||
else
|
}
|
||||||
CGContextSetStrokeColorSpace( ctxRef, patternSpace );
|
CGContextStrokePath(ctxRef);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
baseSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericRGB );
|
|
||||||
patternSpace = CGColorSpaceCreatePattern( baseSpace );
|
|
||||||
|
|
||||||
if (useFill)
|
|
||||||
CGContextSetFillColorSpace( ctxRef, patternSpace );
|
|
||||||
else
|
|
||||||
CGContextSetStrokeColorSpace( ctxRef, patternSpace );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB: the context owns these now, and this code is finished with them
|
virtual void Render( CGContextRef ctxRef )
|
||||||
if (patternSpace != NULL)
|
|
||||||
CGColorSpaceRelease( patternSpace );
|
|
||||||
if (baseSpace != NULL)
|
|
||||||
CGColorSpaceRelease( baseSpace );
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImagePatternRender(
|
|
||||||
void *info,
|
|
||||||
CGContextRef ctxRef )
|
|
||||||
{
|
|
||||||
if (ctxRef == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CGImageRef imageRef = (CGImageRef)info;
|
|
||||||
if (imageRef != NULL)
|
|
||||||
{
|
{
|
||||||
CGRect boundsR = CGRectMake( 0.0, 0.0, (float)CGImageGetWidth( imageRef ), (float)CGImageGetHeight( imageRef ) );
|
switch( m_hatch )
|
||||||
CGContextDrawImage( ctxRef, boundsR, imageRef );
|
{
|
||||||
|
case wxBDIAGONAL_HATCH :
|
||||||
|
{
|
||||||
|
CGPoint pts[] = {
|
||||||
|
{ 8.0 , 0.0 } , { 0.0 , 8.0 }
|
||||||
|
};
|
||||||
|
StrokeLineSegments( ctxRef , pts , 2 ) ;
|
||||||
}
|
}
|
||||||
}
|
break ;
|
||||||
|
case wxCROSSDIAG_HATCH :
|
||||||
void ImagePatternDispose(
|
|
||||||
void *info )
|
|
||||||
{
|
|
||||||
CGImageRef imageRef = (CGImageRef)info;
|
|
||||||
if (imageRef != NULL)
|
|
||||||
CGImageRelease( imageRef );
|
|
||||||
}
|
|
||||||
|
|
||||||
// specifies the struct version value and the callback functions for draw and release
|
|
||||||
static const CGPatternCallbacks sImagePatternCallback = { 0, &ImagePatternRender, &ImagePatternDispose };
|
|
||||||
|
|
||||||
long CreatePatternFromBitmap(
|
|
||||||
CGPatternRef *patternRef,
|
|
||||||
const wxBitmap *rasterInfo,
|
|
||||||
bool useMultibit )
|
|
||||||
{
|
|
||||||
CGRect boundsR;
|
|
||||||
CGImageRef imageRef;
|
|
||||||
long errorStatus, widthV, heightV, depthV;
|
|
||||||
|
|
||||||
if (patternRef == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
*patternRef = NULL;
|
|
||||||
imageRef = NULL;
|
|
||||||
errorStatus = 0;
|
|
||||||
|
|
||||||
if ((rasterInfo == NULL) || !rasterInfo->Ok())
|
|
||||||
errorStatus = (-2);
|
|
||||||
|
|
||||||
if (errorStatus == 0)
|
|
||||||
{
|
{
|
||||||
// build a usable bounding CGRect from the wxBitmap's bounds wxRect
|
CGPoint pts[] = {
|
||||||
widthV = rasterInfo->GetWidth();
|
{ 0.0 , 0.0 } , { 8.0 , 8.0 } ,
|
||||||
heightV = rasterInfo->GetHeight();
|
{ 8.0 , 0.0 } , { 0.0 , 8.0 }
|
||||||
if ((widthV <= 0) || (heightV <= 0))
|
};
|
||||||
errorStatus = (-3);
|
StrokeLineSegments( ctxRef , pts , 4 ) ;
|
||||||
|
}
|
||||||
|
break ;
|
||||||
|
case wxFDIAGONAL_HATCH :
|
||||||
|
{
|
||||||
|
CGPoint pts[] = {
|
||||||
|
{ 0.0 , 0.0 } , { 8.0 , 8.0 }
|
||||||
|
};
|
||||||
|
StrokeLineSegments( ctxRef , pts , 2 ) ;
|
||||||
|
}
|
||||||
|
break ;
|
||||||
|
case wxCROSS_HATCH :
|
||||||
|
{
|
||||||
|
CGPoint pts[] = {
|
||||||
|
{ 0.0 , 4.0 } , { 8.0 , 4.0 } ,
|
||||||
|
{ 4.0 , 0.0 } , { 4.0 , 8.0 } ,
|
||||||
|
};
|
||||||
|
StrokeLineSegments( ctxRef , pts , 4 ) ;
|
||||||
|
}
|
||||||
|
break ;
|
||||||
|
case wxHORIZONTAL_HATCH :
|
||||||
|
{
|
||||||
|
CGPoint pts[] = {
|
||||||
|
{ 0.0 , 4.0 } , { 8.0 , 4.0 } ,
|
||||||
|
};
|
||||||
|
StrokeLineSegments( ctxRef , pts , 2 ) ;
|
||||||
|
}
|
||||||
|
break ;
|
||||||
|
case wxVERTICAL_HATCH :
|
||||||
|
{
|
||||||
|
CGPoint pts[] = {
|
||||||
|
{ 4.0 , 0.0 } , { 4.0 , 8.0 } ,
|
||||||
|
};
|
||||||
|
StrokeLineSegments( ctxRef , pts , 2 ) ;
|
||||||
|
}
|
||||||
|
break ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errorStatus == 0)
|
protected :
|
||||||
|
~HatchPattern()
|
||||||
{
|
{
|
||||||
depthV = rasterInfo->GetDepth();
|
|
||||||
// isColored = (depthV > 1);
|
|
||||||
|
|
||||||
// FIXME: this is often <= 0 - why???
|
|
||||||
// if (depthV <= 1)
|
|
||||||
// errorStatus = (-4);
|
|
||||||
}
|
}
|
||||||
|
int m_hatch ;
|
||||||
|
CGRect m_imageBounds ;
|
||||||
|
} ;
|
||||||
|
|
||||||
if (errorStatus == 0)
|
|
||||||
{
|
|
||||||
imageRef = (CGImageRef)(rasterInfo->CGImageCreate());
|
|
||||||
if (imageRef == NULL)
|
|
||||||
errorStatus = (-5);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errorStatus == 0)
|
|
||||||
{
|
|
||||||
// FIXME: switch when this routine belongs to a DC class...
|
|
||||||
boundsR = CGRectMake( 0.0, 0.0, (float)widthV, (float)heightV );
|
|
||||||
// boundsR = CGRectMake( 0.0, 0.0, (float)XLOG2DEVREL( widthV ), (float)XLOG2DEVREL( heightV ) );
|
|
||||||
|
|
||||||
*patternRef = CGPatternCreate(
|
|
||||||
(void*)imageRef,
|
|
||||||
boundsR,
|
|
||||||
CGAffineTransformIdentity,
|
|
||||||
boundsR.size.width,
|
|
||||||
boundsR.size.height,
|
|
||||||
kCGPatternTilingNoDistortion,
|
|
||||||
(int)useMultibit,
|
|
||||||
&sImagePatternCallback );
|
|
||||||
|
|
||||||
if (*patternRef == (CGPatternRef)NULL)
|
|
||||||
errorStatus = (-6);
|
|
||||||
}
|
|
||||||
|
|
||||||
return errorStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
long CreatePatternFromDashes(
|
|
||||||
CGPatternRef *patternRef,
|
|
||||||
const wxDash *sourceDash,
|
|
||||||
int count,
|
|
||||||
bool useMultibit )
|
|
||||||
{
|
|
||||||
long errorStatus;
|
|
||||||
|
|
||||||
if (patternRef == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
*patternRef = NULL;
|
|
||||||
if ((sourceDash == NULL) || (count <= 0))
|
|
||||||
return (-2);
|
|
||||||
|
|
||||||
wxBitmap dashBits( (char*)sourceDash, 8, count, 1 );
|
|
||||||
errorStatus = CreatePatternFromBitmap( patternRef, &dashBits, useMultibit );
|
|
||||||
|
|
||||||
return errorStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
long CreatePatternFromBrush(
|
|
||||||
CGPatternRef *patternRef,
|
|
||||||
const wxBrush &sourceBrush,
|
|
||||||
bool useMultibit )
|
|
||||||
{
|
|
||||||
long errorStatus;
|
|
||||||
|
|
||||||
if (patternRef == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
*patternRef = NULL;
|
|
||||||
errorStatus = CreatePatternFromBitmap( patternRef, sourceBrush.GetStipple(), useMultibit );
|
|
||||||
|
|
||||||
return errorStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
long CreatePatternFromPen(
|
|
||||||
CGPatternRef *patternRef,
|
|
||||||
const wxPen &sourcePen,
|
|
||||||
bool useMultibit )
|
|
||||||
{
|
|
||||||
long errorStatus;
|
|
||||||
|
|
||||||
if (patternRef == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
*patternRef = NULL;
|
|
||||||
errorStatus = CreatePatternFromBitmap( patternRef, sourcePen.GetStipple(), useMultibit );
|
|
||||||
|
|
||||||
return errorStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------
|
|
||||||
#pragma mark -
|
|
||||||
|
|
||||||
// FIXME: the NEW_GC_SUPPORT part this routine is unfinished and needs lots of work !!
|
|
||||||
//
|
|
||||||
void wxMacCGContext::SetPen( const wxPen &pen )
|
void wxMacCGContext::SetPen( const wxPen &pen )
|
||||||
{
|
{
|
||||||
m_pen = pen ;
|
m_pen = pen ;
|
||||||
@@ -529,55 +510,14 @@ void wxMacCGContext::SetPen( const wxPen &pen )
|
|||||||
}
|
}
|
||||||
if ( stroke )
|
if ( stroke )
|
||||||
{
|
{
|
||||||
#if defined(_NEW_GC_SUPPORT_)
|
|
||||||
// new candidate
|
|
||||||
{
|
|
||||||
CGPatternRef patternRef;
|
|
||||||
float alphaArray[1];
|
|
||||||
long result;
|
|
||||||
bool hasSetPattern, useMultibit;
|
|
||||||
|
|
||||||
hasSetPattern = false;
|
|
||||||
useMultibit = true;
|
|
||||||
result = CreatePatternFromPen( &patternRef, pen, useMultibit );
|
|
||||||
if (result == 0)
|
|
||||||
{
|
|
||||||
EstablishPatternColorSpace( m_cgContext, useMultibit, false );
|
|
||||||
|
|
||||||
alphaArray[0] = 1.0;
|
|
||||||
CGContextSetStrokePattern( m_cgContext, patternRef, alphaArray );
|
|
||||||
CGPatternRelease( patternRef );
|
|
||||||
|
|
||||||
hasSetPattern = true;
|
|
||||||
|
|
||||||
//wxLogDebug( wxT("CreatePatternFromPen succeeded!") );
|
|
||||||
}
|
|
||||||
|
|
||||||
// NB: the (-2) result is from wxPen instances that don't have a stipple wxBitmap
|
|
||||||
if (result < (-2))
|
|
||||||
wxLogDebug( wxT("CreatePatternFromPen failed: result [%ld]"), result );
|
|
||||||
|
|
||||||
if (!hasSetPattern)
|
|
||||||
{
|
|
||||||
RGBColor col;
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
col = MAC_WXCOLORREF( pen.GetColour().GetPixel() );
|
|
||||||
#else
|
|
||||||
GetThemeBrushAsColor( pen.MacGetTheme(), 32, true, &col );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CGContextSetRGBStrokeColor(
|
|
||||||
m_cgContext, (float) col.red / 65536.0,
|
|
||||||
(float) col.green / 65536.0, (float) col.blue / 65536.0, 1.0 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
// original implementation
|
|
||||||
RGBColor col = MAC_WXCOLORREF( pen.GetColour().GetPixel() ) ;
|
RGBColor col = MAC_WXCOLORREF( pen.GetColour().GetPixel() ) ;
|
||||||
CGContextSetRGBStrokeColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
|
CGContextSetRGBStrokeColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
|
||||||
#endif
|
|
||||||
|
/* TODO * m_dc->m_scaleX */
|
||||||
|
float penWidth = pen.GetWidth();
|
||||||
|
if (penWidth <= 0.0)
|
||||||
|
penWidth = 0.1;
|
||||||
|
CGContextSetLineWidth( m_cgContext , penWidth ) ;
|
||||||
|
|
||||||
CGLineCap cap ;
|
CGLineCap cap ;
|
||||||
switch( pen.GetCap() )
|
switch( pen.GetCap() )
|
||||||
@@ -595,7 +535,6 @@ void wxMacCGContext::SetPen( const wxPen &pen )
|
|||||||
cap = kCGLineCapButt ;
|
cap = kCGLineCapButt ;
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
CGContextSetLineCap( m_cgContext , cap ) ;
|
|
||||||
|
|
||||||
CGLineJoin join ;
|
CGLineJoin join ;
|
||||||
switch( pen.GetJoin() )
|
switch( pen.GetJoin() )
|
||||||
@@ -615,90 +554,19 @@ void wxMacCGContext::SetPen( const wxPen &pen )
|
|||||||
}
|
}
|
||||||
CGContextSetLineJoin( m_cgContext , join ) ;
|
CGContextSetLineJoin( m_cgContext , join ) ;
|
||||||
|
|
||||||
/* TODO * m_dc->m_scaleX */
|
|
||||||
float penWidth = pen.GetWidth();
|
|
||||||
if (penWidth <= 0.0)
|
|
||||||
penWidth = 0.1;
|
|
||||||
CGContextSetLineWidth( m_cgContext , penWidth ) ;
|
|
||||||
|
|
||||||
m_mode = kCGPathStroke ;
|
m_mode = kCGPathStroke ;
|
||||||
int count = 0 ;
|
int count = 0 ;
|
||||||
|
|
||||||
#if defined(_NEW_GC_DASHES_)
|
|
||||||
const char *dashData = NULL ;
|
|
||||||
char *userDashData = NULL ;
|
|
||||||
float alphaArray[1];
|
|
||||||
|
|
||||||
const char dotted[] = { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 };
|
|
||||||
const char dashed[] = { 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00 };
|
|
||||||
const char short_dashed[] = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 };
|
|
||||||
const char dotted_dashed[] = { 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00 };
|
|
||||||
|
|
||||||
switch (pen.GetStyle())
|
|
||||||
{
|
|
||||||
case wxSOLID:
|
|
||||||
// default, undashed pen
|
|
||||||
break;
|
|
||||||
|
|
||||||
case wxDOT:
|
|
||||||
dashData = dotted;
|
|
||||||
count = WXSIZEOF(dotted);
|
|
||||||
break;
|
|
||||||
case wxLONG_DASH:
|
|
||||||
dashData = dashed;
|
|
||||||
count = WXSIZEOF(dashed);
|
|
||||||
break;
|
|
||||||
case wxSHORT_DASH:
|
|
||||||
dashData = short_dashed;
|
|
||||||
count = WXSIZEOF(short_dashed);
|
|
||||||
break;
|
|
||||||
case wxDOT_DASH:
|
|
||||||
dashData = dotted_dashed;
|
|
||||||
count = WXSIZEOF(dotted_dashed);
|
|
||||||
break;
|
|
||||||
case wxUSER_DASH:
|
|
||||||
count = pen.GetDashes( (wxDash**)&userDashData );
|
|
||||||
dashData = userDashData;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default :
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((dashData != NULL) && (count > 0))
|
|
||||||
{
|
|
||||||
CGPatternRef patternRef;
|
|
||||||
RGBColor col;
|
|
||||||
long result;
|
|
||||||
bool useMultibit;
|
|
||||||
|
|
||||||
useMultibit = true;
|
|
||||||
result = CreatePatternFromDashes( &patternRef, (const wxDash*)dashData, count, useMultibit );
|
|
||||||
if (result == 0)
|
|
||||||
{
|
|
||||||
col = MAC_WXCOLORREF( pen.GetColour().GetPixel() );
|
|
||||||
CGContextSetRGBStrokeColor(
|
|
||||||
m_cgContext, (float) col.red / 65536.0,
|
|
||||||
(float) col.green / 65536.0, (float) col.blue / 65536.0, 1.0 );
|
|
||||||
|
|
||||||
EstablishPatternColorSpace( m_cgContext, useMultibit, false );
|
|
||||||
|
|
||||||
alphaArray[0] = 1.0;
|
|
||||||
CGContextSetStrokePattern( m_cgContext, patternRef, alphaArray );
|
|
||||||
CGPatternRelease( patternRef );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != 0)
|
|
||||||
wxLogDebug( wxT("CreatePatternFromDashes failed: result [%ld]"), result );
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
const float *lengths = NULL ;
|
const float *lengths = NULL ;
|
||||||
float *userLengths = NULL ;
|
float *userLengths = NULL ;
|
||||||
|
|
||||||
const float dotted[] = { 3 , 3 };
|
int dashUnit = ( penWidth < 1.0 ) ? 1.0 : penWidth;
|
||||||
const float dashed[] = { 19 , 9 };
|
|
||||||
const float short_dashed[] = { 9 , 6 };
|
const float dotted[] = { dashUnit , dashUnit + 2.0 };
|
||||||
const float dotted_dashed[] = { 9 , 6 , 3 , 3 };
|
const float short_dashed[] = { 9.0 , 6.0 };
|
||||||
|
const float dashed[] = { 19.0 , 9.0 };
|
||||||
|
const float dotted_dashed[] = { 9.0 , 6.0 , 3.0 , 3.0 };
|
||||||
|
|
||||||
|
|
||||||
switch( pen.GetStyle() )
|
switch( pen.GetStyle() )
|
||||||
{
|
{
|
||||||
@@ -728,34 +596,56 @@ void wxMacCGContext::SetPen( const wxPen &pen )
|
|||||||
userLengths = new float[count] ;
|
userLengths = new float[count] ;
|
||||||
for( int i = 0 ; i < count ; ++i )
|
for( int i = 0 ; i < count ; ++i )
|
||||||
{
|
{
|
||||||
userLengths[i] = (float)dashes[i] ;
|
userLengths[i] = (float)dashes[i] * dashUnit ;
|
||||||
if (userLengths[i] <= 0.0)
|
|
||||||
{
|
if ( i % 2 == 1 && userLengths[i] < dashUnit + 2.0 )
|
||||||
userLengths[i] = 1.0;
|
userLengths[i] = dashUnit + 2.0 ;
|
||||||
// wxLogDebug( wxT("wxMacCGContext::SetPen - bad dash length[%d] [%.2f]"), i, (float)dashes[i] );
|
else if ( i % 2 == 0 && userLengths[i] < dashUnit )
|
||||||
}
|
userLengths[i] = dashUnit ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lengths = userLengths ;
|
lengths = userLengths ;
|
||||||
break ;
|
break ;
|
||||||
|
case wxSTIPPLE :
|
||||||
|
{
|
||||||
|
float alphaArray[1] = { 1.0 } ;
|
||||||
|
wxBitmap* bmp = pen.GetStipple() ;
|
||||||
|
if ( bmp && bmp->Ok() )
|
||||||
|
{
|
||||||
|
wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( NULL ) ) ;
|
||||||
|
CGContextSetStrokeColorSpace( m_cgContext , patternSpace ) ;
|
||||||
|
wxMacCFRefHolder<CGPatternRef> pattern( *( new ImagePattern( bmp , CGContextGetCTM( m_cgContext ) ) ) );
|
||||||
|
CGContextSetStrokePattern( m_cgContext, pattern , alphaArray ) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break ;
|
||||||
default :
|
default :
|
||||||
|
{
|
||||||
|
wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ) ;
|
||||||
|
CGContextSetStrokeColorSpace( m_cgContext , patternSpace ) ;
|
||||||
|
wxMacCFRefHolder<CGPatternRef> pattern( *( new HatchPattern( pen.GetStyle() , CGContextGetCTM( m_cgContext ) ) ) );
|
||||||
|
|
||||||
|
RGBColor col = MAC_WXCOLORREF( pen.GetColour().GetPixel() ) ;
|
||||||
|
float colorArray[4] = { col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 } ;
|
||||||
|
|
||||||
|
CGContextSetStrokePattern( m_cgContext, pattern , colorArray ) ;
|
||||||
|
}
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((lengths != NULL) && (count > 0))
|
if ((lengths != NULL) && (count > 0))
|
||||||
{
|
{
|
||||||
// we need to change the cap, otherwise everything overlaps
|
|
||||||
// and we get solid lines
|
|
||||||
CGContextSetLineDash( m_cgContext , 0 , lengths , count ) ;
|
CGContextSetLineDash( m_cgContext , 0 , lengths , count ) ;
|
||||||
CGContextSetLineCap( m_cgContext , kCGLineCapButt ) ;
|
// force the line cap, otherwise we get artifacts (overlaps) and just solid lines
|
||||||
|
cap = kCGLineCapButt ;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CGContextSetLineDash( m_cgContext , 0 , NULL , 0 ) ;
|
CGContextSetLineDash( m_cgContext , 0 , NULL , 0 ) ;
|
||||||
}
|
}
|
||||||
|
CGContextSetLineCap( m_cgContext , cap ) ;
|
||||||
|
|
||||||
delete[] userLengths ;
|
delete[] userLengths ;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if ( fill && stroke )
|
if ( fill && stroke )
|
||||||
{
|
{
|
||||||
@@ -785,56 +675,35 @@ void wxMacCGContext::SetBrush( const wxBrush &brush )
|
|||||||
|
|
||||||
if ( fill )
|
if ( fill )
|
||||||
{
|
{
|
||||||
#if defined(_NEW_GC_SUPPORT_)
|
if ( brush.GetStyle() == wxSOLID )
|
||||||
// new candidate
|
|
||||||
{
|
{
|
||||||
CGPatternRef patternRef;
|
|
||||||
float alphaArray[1];
|
|
||||||
long result;
|
|
||||||
bool hasSetPattern, useMultibit;
|
|
||||||
|
|
||||||
hasSetPattern = false;
|
|
||||||
useMultibit = true;
|
|
||||||
result = CreatePatternFromBrush( &patternRef, brush, useMultibit );
|
|
||||||
if (result == 0)
|
|
||||||
{
|
|
||||||
EstablishPatternColorSpace( m_cgContext, useMultibit, true );
|
|
||||||
|
|
||||||
alphaArray[0] = 1.0;
|
|
||||||
CGContextSetFillPattern( m_cgContext, patternRef, alphaArray );
|
|
||||||
CGPatternRelease( patternRef );
|
|
||||||
|
|
||||||
hasSetPattern = true;
|
|
||||||
|
|
||||||
//wxLogDebug( wxT("CreatePatternFromBrush succeeded!") );
|
|
||||||
}
|
|
||||||
|
|
||||||
// NB: the (-2) result is from wxBrush instances that don't have a stipple wxBitmap
|
|
||||||
if (result < (-2))
|
|
||||||
wxLogDebug( wxT("CreatePatternFromBrush failed: result [%ld]"), result );
|
|
||||||
|
|
||||||
if (!hasSetPattern)
|
|
||||||
{
|
|
||||||
RGBColor col;
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
col = MAC_WXCOLORREF( brush.GetColour().GetPixel() );
|
|
||||||
#else
|
|
||||||
GetThemeBrushAsColor( brush.MacGetTheme(), 32, true, &col );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CGContextSetRGBFillColor(
|
|
||||||
m_cgContext, (float) col.red / 65536.0,
|
|
||||||
(float) col.green / 65536.0, (float) col.blue / 65536.0, 1.0 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
// original implementation
|
|
||||||
RGBColor col = MAC_WXCOLORREF( brush.GetColour().GetPixel() ) ;
|
RGBColor col = MAC_WXCOLORREF( brush.GetColour().GetPixel() ) ;
|
||||||
CGContextSetRGBFillColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
|
CGContextSetRGBFillColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
|
||||||
#endif
|
}
|
||||||
|
else if ( brush.IsHatch() )
|
||||||
|
{
|
||||||
|
wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ) ;
|
||||||
|
CGContextSetFillColorSpace( m_cgContext , patternSpace ) ;
|
||||||
|
wxMacCFRefHolder<CGPatternRef> pattern( *( new HatchPattern( brush.GetStyle() , CGContextGetCTM( m_cgContext ) ) ) );
|
||||||
|
|
||||||
|
RGBColor col = MAC_WXCOLORREF( brush.GetColour().GetPixel() ) ;
|
||||||
|
float colorArray[4] = { col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 } ;
|
||||||
|
|
||||||
|
CGContextSetFillPattern( m_cgContext, pattern , colorArray ) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// now brush is a bitmap
|
||||||
|
float alphaArray[1] = { 1.0 } ;
|
||||||
|
wxBitmap* bmp = brush.GetStipple() ;
|
||||||
|
if ( bmp && bmp->Ok() )
|
||||||
|
{
|
||||||
|
wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( NULL ) ) ;
|
||||||
|
CGContextSetFillColorSpace( m_cgContext , patternSpace ) ;
|
||||||
|
wxMacCFRefHolder<CGPatternRef> pattern( *( new ImagePattern( bmp , CGContextGetCTM( m_cgContext ) ) ) );
|
||||||
|
CGContextSetFillPattern( m_cgContext, pattern , alphaArray ) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
m_mode = kCGPathFill ;
|
m_mode = kCGPathFill ;
|
||||||
}
|
}
|
||||||
if ( stroke )
|
if ( stroke )
|
||||||
@@ -888,8 +757,7 @@ wxDC::wxDC()
|
|||||||
m_colour = TRUE;
|
m_colour = TRUE;
|
||||||
m_mm_to_pix_x = mm2pt;
|
m_mm_to_pix_x = mm2pt;
|
||||||
m_mm_to_pix_y = mm2pt;
|
m_mm_to_pix_y = mm2pt;
|
||||||
m_internalDeviceOriginX = 0;
|
|
||||||
m_internalDeviceOriginY = 0;
|
|
||||||
m_externalDeviceOriginX = 0;
|
m_externalDeviceOriginX = 0;
|
||||||
m_externalDeviceOriginY = 0;
|
m_externalDeviceOriginY = 0;
|
||||||
m_logicalScaleX = 1.0;
|
m_logicalScaleX = 1.0;
|
||||||
@@ -1166,8 +1034,8 @@ void wxDC::ComputeScaleAndOrigin()
|
|||||||
double origScaleY = m_scaleY;
|
double origScaleY = m_scaleY;
|
||||||
m_scaleX = m_logicalScaleX * m_userScaleX;
|
m_scaleX = m_logicalScaleX * m_userScaleX;
|
||||||
m_scaleY = m_logicalScaleY * m_userScaleY;
|
m_scaleY = m_logicalScaleY * m_userScaleY;
|
||||||
m_deviceOriginX = m_internalDeviceOriginX + m_externalDeviceOriginX;
|
m_deviceOriginX = m_externalDeviceOriginX;
|
||||||
m_deviceOriginY = m_internalDeviceOriginY + m_externalDeviceOriginY;
|
m_deviceOriginY = m_externalDeviceOriginY;
|
||||||
// CMB: if scale has changed call SetPen to recalulate the line width
|
// CMB: if scale has changed call SetPen to recalulate the line width
|
||||||
if (m_scaleX != origScaleX || m_scaleY != origScaleY)
|
if (m_scaleX != origScaleX || m_scaleY != origScaleY)
|
||||||
{
|
{
|
||||||
@@ -1200,9 +1068,23 @@ void wxDC::SetPen( const wxPen &pen )
|
|||||||
return ;
|
return ;
|
||||||
m_pen = pen;
|
m_pen = pen;
|
||||||
if ( m_graphicContext )
|
if ( m_graphicContext )
|
||||||
|
{
|
||||||
|
if ( m_pen.GetStyle() == wxSOLID || m_pen.GetStyle() == wxTRANSPARENT )
|
||||||
{
|
{
|
||||||
m_graphicContext->SetPen( m_pen ) ;
|
m_graphicContext->SetPen( m_pen ) ;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// we have to compensate for moved device origins etc. otherwise patterned pens are standing still
|
||||||
|
// eg when using a wxScrollWindow and scrolling around
|
||||||
|
CGContextRef cgContext = ((wxMacCGContext*)(m_graphicContext))->GetNativeContext() ;
|
||||||
|
int origX = XLOG2DEVMAC(0) ;
|
||||||
|
int origY = YLOG2DEVMAC(0) ;
|
||||||
|
CGContextTranslateCTM (cgContext,origX,origY);
|
||||||
|
m_graphicContext->SetPen( m_pen ) ;
|
||||||
|
CGContextTranslateCTM (cgContext,-origX,-origY);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxDC::SetBrush( const wxBrush &brush )
|
void wxDC::SetBrush( const wxBrush &brush )
|
||||||
@@ -1211,9 +1093,23 @@ void wxDC::SetBrush( const wxBrush &brush )
|
|||||||
return;
|
return;
|
||||||
m_brush = brush;
|
m_brush = brush;
|
||||||
if ( m_graphicContext )
|
if ( m_graphicContext )
|
||||||
|
{
|
||||||
|
if ( brush.GetStyle() == wxSOLID || brush.GetStyle() == wxTRANSPARENT )
|
||||||
{
|
{
|
||||||
m_graphicContext->SetBrush( m_brush ) ;
|
m_graphicContext->SetBrush( m_brush ) ;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// we have to compensate for moved device origins etc. otherwise patterned brushes are standing still
|
||||||
|
// eg when using a wxScrollWindow and scrolling around
|
||||||
|
CGContextRef cgContext = ((wxMacCGContext*)(m_graphicContext))->GetNativeContext() ;
|
||||||
|
int origX = XLOG2DEVMAC(0) ;
|
||||||
|
int origY = YLOG2DEVMAC(0) ;
|
||||||
|
CGContextTranslateCTM (cgContext,origX,origY);
|
||||||
|
m_graphicContext->SetBrush( m_brush ) ;
|
||||||
|
CGContextTranslateCTM (cgContext,-origX,-origY);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxDC::SetBackground( const wxBrush &brush )
|
void wxDC::SetBackground( const wxBrush &brush )
|
||||||
@@ -1542,7 +1438,7 @@ void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
|
|||||||
yy = yy - hh;
|
yy = yy - hh;
|
||||||
}
|
}
|
||||||
wxGraphicPath* path = m_graphicContext->CreatePath() ;
|
wxGraphicPath* path = m_graphicContext->CreatePath() ;
|
||||||
path->AddRectangle(xx ,yy , ww , hh ) ;
|
path->AddRectangle( xx , yy , ww , hh ) ;
|
||||||
m_graphicContext->DrawPath( path ) ;
|
m_graphicContext->DrawPath( path ) ;
|
||||||
delete path ;
|
delete path ;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user