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:
parent
bf00c875fe
commit
24cd6f8250
@ -304,208 +304,189 @@ void wxMacCGContext::SetNativeContext( CGContextRef cg )
|
||||
|
||||
#pragma mark -
|
||||
|
||||
// Experimental support for dashes and patterned brushes
|
||||
// uncomment the following lines to enable it
|
||||
// wrapper class for a CGPattern, always allocate on heap, never call destructor
|
||||
|
||||
// #define _NEW_GC_DASHES_
|
||||
// #define _NEW_GC_SUPPORT_
|
||||
class wxMacCGPattern
|
||||
{
|
||||
public :
|
||||
wxMacCGPattern()
|
||||
{
|
||||
}
|
||||
|
||||
// is guaranteed to be called only with a non-Null CGContextRef
|
||||
virtual void Render( CGContextRef ctxRef ) = 0 ;
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4
|
||||
#define kCGColorSpaceGenericRGB CFSTR("kCGColorSpaceGenericRGB")
|
||||
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
|
||||
{
|
||||
CGContextBeginPath (ctxRef);
|
||||
for (size_t i = 0; i < count; i += 2) {
|
||||
CGContextMoveToPoint(ctxRef, pts[i].x, pts[i].y);
|
||||
CGContextAddLineToPoint(ctxRef, pts[i+1].x, pts[i+1].y);
|
||||
}
|
||||
CGContextStrokePath(ctxRef);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Render( CGContextRef ctxRef )
|
||||
{
|
||||
switch( m_hatch )
|
||||
{
|
||||
case wxBDIAGONAL_HATCH :
|
||||
{
|
||||
CGPoint pts[] = {
|
||||
{ 8.0 , 0.0 } , { 0.0 , 8.0 }
|
||||
};
|
||||
StrokeLineSegments( ctxRef , pts , 2 ) ;
|
||||
}
|
||||
break ;
|
||||
case wxCROSSDIAG_HATCH :
|
||||
{
|
||||
CGPoint pts[] = {
|
||||
{ 0.0 , 0.0 } , { 8.0 , 8.0 } ,
|
||||
{ 8.0 , 0.0 } , { 0.0 , 8.0 }
|
||||
};
|
||||
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 ;
|
||||
}
|
||||
}
|
||||
|
||||
protected :
|
||||
~HatchPattern()
|
||||
{
|
||||
}
|
||||
int m_hatch ;
|
||||
CGRect m_imageBounds ;
|
||||
} ;
|
||||
|
||||
void EstablishPatternColorSpace(
|
||||
CGContextRef ctxRef,
|
||||
bool useMultibit,
|
||||
bool useFill )
|
||||
{
|
||||
CGColorSpaceRef baseSpace, patternSpace;
|
||||
|
||||
if (ctxRef == NULL)
|
||||
return;
|
||||
|
||||
baseSpace = NULL;
|
||||
patternSpace = NULL;
|
||||
|
||||
if (useMultibit)
|
||||
{
|
||||
patternSpace = CGColorSpaceCreatePattern( NULL );
|
||||
|
||||
if (useFill)
|
||||
CGContextSetFillColorSpace( ctxRef, patternSpace );
|
||||
else
|
||||
CGContextSetStrokeColorSpace( ctxRef, patternSpace );
|
||||
}
|
||||
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
|
||||
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 ) );
|
||||
CGContextDrawImage( ctxRef, boundsR, imageRef );
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
widthV = rasterInfo->GetWidth();
|
||||
heightV = rasterInfo->GetHeight();
|
||||
if ((widthV <= 0) || (heightV <= 0))
|
||||
errorStatus = (-3);
|
||||
}
|
||||
|
||||
if (errorStatus == 0)
|
||||
{
|
||||
depthV = rasterInfo->GetDepth();
|
||||
// isColored = (depthV > 1);
|
||||
|
||||
// FIXME: this is often <= 0 - why???
|
||||
// if (depthV <= 1)
|
||||
// errorStatus = (-4);
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
m_pen = pen ;
|
||||
@ -529,55 +510,14 @@ void wxMacCGContext::SetPen( const wxPen &pen )
|
||||
}
|
||||
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() ) ;
|
||||
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 ;
|
||||
switch( pen.GetCap() )
|
||||
@ -595,7 +535,6 @@ void wxMacCGContext::SetPen( const wxPen &pen )
|
||||
cap = kCGLineCapButt ;
|
||||
break ;
|
||||
}
|
||||
CGContextSetLineCap( m_cgContext , cap ) ;
|
||||
|
||||
CGLineJoin join ;
|
||||
switch( pen.GetJoin() )
|
||||
@ -615,91 +554,20 @@ void wxMacCGContext::SetPen( const wxPen &pen )
|
||||
}
|
||||
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 ;
|
||||
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 ;
|
||||
float *userLengths = NULL ;
|
||||
|
||||
const float dotted[] = { 3 , 3 };
|
||||
const float dashed[] = { 19 , 9 };
|
||||
const float short_dashed[] = { 9 , 6 };
|
||||
const float dotted_dashed[] = { 9 , 6 , 3 , 3 };
|
||||
|
||||
|
||||
int dashUnit = ( penWidth < 1.0 ) ? 1.0 : penWidth;
|
||||
|
||||
const float dotted[] = { dashUnit , dashUnit + 2.0 };
|
||||
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() )
|
||||
{
|
||||
case wxSOLID :
|
||||
@ -728,34 +596,56 @@ void wxMacCGContext::SetPen( const wxPen &pen )
|
||||
userLengths = new float[count] ;
|
||||
for( int i = 0 ; i < count ; ++i )
|
||||
{
|
||||
userLengths[i] = (float)dashes[i] ;
|
||||
if (userLengths[i] <= 0.0)
|
||||
{
|
||||
userLengths[i] = 1.0;
|
||||
// wxLogDebug( wxT("wxMacCGContext::SetPen - bad dash length[%d] [%.2f]"), i, (float)dashes[i] );
|
||||
}
|
||||
userLengths[i] = (float)dashes[i] * dashUnit ;
|
||||
|
||||
if ( i % 2 == 1 && userLengths[i] < dashUnit + 2.0 )
|
||||
userLengths[i] = dashUnit + 2.0 ;
|
||||
else if ( i % 2 == 0 && userLengths[i] < dashUnit )
|
||||
userLengths[i] = dashUnit ;
|
||||
}
|
||||
}
|
||||
lengths = userLengths ;
|
||||
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 :
|
||||
{
|
||||
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 ;
|
||||
}
|
||||
|
||||
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 ) ;
|
||||
CGContextSetLineCap( m_cgContext , kCGLineCapButt ) ;
|
||||
// force the line cap, otherwise we get artifacts (overlaps) and just solid lines
|
||||
cap = kCGLineCapButt ;
|
||||
}
|
||||
else
|
||||
{
|
||||
CGContextSetLineDash( m_cgContext , 0 , NULL , 0 ) ;
|
||||
}
|
||||
CGContextSetLineCap( m_cgContext , cap ) ;
|
||||
|
||||
delete[] userLengths ;
|
||||
#endif
|
||||
}
|
||||
if ( fill && stroke )
|
||||
{
|
||||
@ -785,56 +675,35 @@ void wxMacCGContext::SetBrush( const wxBrush &brush )
|
||||
|
||||
if ( fill )
|
||||
{
|
||||
#if defined(_NEW_GC_SUPPORT_)
|
||||
// new candidate
|
||||
if ( brush.GetStyle() == wxSOLID )
|
||||
{
|
||||
CGPatternRef patternRef;
|
||||
float alphaArray[1];
|
||||
long result;
|
||||
bool hasSetPattern, useMultibit;
|
||||
RGBColor col = MAC_WXCOLORREF( brush.GetColour().GetPixel() ) ;
|
||||
CGContextSetRGBFillColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
|
||||
}
|
||||
else if ( brush.IsHatch() )
|
||||
{
|
||||
wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) ) ;
|
||||
CGContextSetFillColorSpace( m_cgContext , patternSpace ) ;
|
||||
wxMacCFRefHolder<CGPatternRef> pattern( *( new HatchPattern( brush.GetStyle() , CGContextGetCTM( m_cgContext ) ) ) );
|
||||
|
||||
hasSetPattern = false;
|
||||
useMultibit = true;
|
||||
result = CreatePatternFromBrush( &patternRef, brush, useMultibit );
|
||||
if (result == 0)
|
||||
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() )
|
||||
{
|
||||
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 );
|
||||
wxMacCFRefHolder<CGColorSpaceRef> patternSpace( CGColorSpaceCreatePattern( NULL ) ) ;
|
||||
CGContextSetFillColorSpace( m_cgContext , patternSpace ) ;
|
||||
wxMacCFRefHolder<CGPatternRef> pattern( *( new ImagePattern( bmp , CGContextGetCTM( m_cgContext ) ) ) );
|
||||
CGContextSetFillPattern( m_cgContext, pattern , alphaArray ) ;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
// original implementation
|
||||
RGBColor col = MAC_WXCOLORREF( brush.GetColour().GetPixel() ) ;
|
||||
CGContextSetRGBFillColor( m_cgContext , col.red / 65536.0 , col.green / 65536.0 , col.blue / 65536.0 , 1.0 ) ;
|
||||
#endif
|
||||
|
||||
m_mode = kCGPathFill ;
|
||||
}
|
||||
if ( stroke )
|
||||
@ -888,8 +757,7 @@ wxDC::wxDC()
|
||||
m_colour = TRUE;
|
||||
m_mm_to_pix_x = mm2pt;
|
||||
m_mm_to_pix_y = mm2pt;
|
||||
m_internalDeviceOriginX = 0;
|
||||
m_internalDeviceOriginY = 0;
|
||||
|
||||
m_externalDeviceOriginX = 0;
|
||||
m_externalDeviceOriginY = 0;
|
||||
m_logicalScaleX = 1.0;
|
||||
@ -1166,8 +1034,8 @@ void wxDC::ComputeScaleAndOrigin()
|
||||
double origScaleY = m_scaleY;
|
||||
m_scaleX = m_logicalScaleX * m_userScaleX;
|
||||
m_scaleY = m_logicalScaleY * m_userScaleY;
|
||||
m_deviceOriginX = m_internalDeviceOriginX + m_externalDeviceOriginX;
|
||||
m_deviceOriginY = m_internalDeviceOriginY + m_externalDeviceOriginY;
|
||||
m_deviceOriginX = m_externalDeviceOriginX;
|
||||
m_deviceOriginY = m_externalDeviceOriginY;
|
||||
// CMB: if scale has changed call SetPen to recalulate the line width
|
||||
if (m_scaleX != origScaleX || m_scaleY != origScaleY)
|
||||
{
|
||||
@ -1201,7 +1069,21 @@ void wxDC::SetPen( const wxPen &pen )
|
||||
m_pen = pen;
|
||||
if ( m_graphicContext )
|
||||
{
|
||||
m_graphicContext->SetPen( m_pen ) ;
|
||||
if ( m_pen.GetStyle() == wxSOLID || m_pen.GetStyle() == wxTRANSPARENT )
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1212,7 +1094,21 @@ void wxDC::SetBrush( const wxBrush &brush )
|
||||
m_brush = brush;
|
||||
if ( m_graphicContext )
|
||||
{
|
||||
m_graphicContext->SetBrush( m_brush ) ;
|
||||
if ( brush.GetStyle() == wxSOLID || brush.GetStyle() == wxTRANSPARENT )
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1542,7 +1438,7 @@ void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
|
||||
yy = yy - hh;
|
||||
}
|
||||
wxGraphicPath* path = m_graphicContext->CreatePath() ;
|
||||
path->AddRectangle(xx ,yy , ww , hh ) ;
|
||||
path->AddRectangle( xx , yy , ww , hh ) ;
|
||||
m_graphicContext->DrawPath( path ) ;
|
||||
delete path ;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user