PageRenderTime 54ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/ExtLibs/wxWidgets/src/osx/carbon/graphics.cpp

https://bitbucket.org/lennonchan/cafu
C++ | 1632 lines | 1159 code | 302 blank | 171 comment | 80 complexity | 5414cf5d79cbf3aee6e1e5b083fa8247 MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: src/osx/carbon/graphics.cpp
  3. // Purpose: wxDC class
  4. // Author: Stefan Csomor
  5. // Modified by:
  6. // Created: 01/02/97
  7. // RCS-ID: $Id$
  8. // copyright: (c) Stefan Csomor
  9. // Licence: wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11. #include "wx/wxprec.h"
  12. #include "wx/graphics.h"
  13. #include "wx/private/graphics.h"
  14. #ifndef WX_PRECOMP
  15. #include "wx/dcclient.h"
  16. #include "wx/dcmemory.h"
  17. #include "wx/dcprint.h"
  18. #include "wx/log.h"
  19. #include "wx/region.h"
  20. #include "wx/image.h"
  21. #include "wx/icon.h"
  22. #endif
  23. #ifdef __MSL__
  24. #if __MSL__ >= 0x6000
  25. #include "math.h"
  26. // in case our functions were defined outside std, we make it known all the same
  27. namespace std { }
  28. using namespace std;
  29. #endif
  30. #endif
  31. #ifdef __WXMAC__
  32. #include "wx/osx/private.h"
  33. #include "wx/osx/dcprint.h"
  34. #include "wx/osx/dcclient.h"
  35. #include "wx/osx/dcmemory.h"
  36. #include "wx/osx/private.h"
  37. #else
  38. #include "CoreServices/CoreServices.h"
  39. #include "ApplicationServices/ApplicationServices.h"
  40. #include "wx/osx/core/cfstring.h"
  41. #include "wx/cocoa/dcclient.h"
  42. #endif
  43. #ifdef __WXCOCOA__
  44. CGColorSpaceRef wxMacGetGenericRGBColorSpace()
  45. {
  46. static wxCFRef<CGColorSpaceRef> genericRGBColorSpace;
  47. if (genericRGBColorSpace == NULL)
  48. {
  49. genericRGBColorSpace.reset( CGColorSpaceCreateWithName( kCGColorSpaceGenericRGB ) );
  50. }
  51. return genericRGBColorSpace;
  52. }
  53. int UMAGetSystemVersion()
  54. {
  55. return 0x1050;
  56. }
  57. #define wxOSX_USE_CORE_TEXT 1
  58. #endif
  59. #if wxOSX_USE_COCOA_OR_IPHONE
  60. extern CGContextRef wxOSXGetContextFromCurrentContext() ;
  61. #if wxOSX_USE_COCOA
  62. extern bool wxOSXLockFocus( WXWidget view) ;
  63. extern void wxOSXUnlockFocus( WXWidget view) ;
  64. #endif
  65. #endif
  66. #if 1 // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  67. // TODO test whether this private API also works under 10.3
  68. // copying values from NSCompositingModes (see also webkit and cairo sources)
  69. typedef enum CGCompositeOperation {
  70. kCGCompositeOperationClear = 0,
  71. kCGCompositeOperationCopy = 1,
  72. kCGCompositeOperationSourceOver = 2,
  73. kCGCompositeOperationSourceIn = 3,
  74. kCGCompositeOperationSourceOut = 4,
  75. kCGCompositeOperationSourceAtop = 5,
  76. kCGCompositeOperationDestinationOver = 6,
  77. kCGCompositeOperationDestinationIn = 7,
  78. kCGCompositeOperationDestinationOut = 8,
  79. kCGCompositeOperationDestinationAtop = 9,
  80. kCGCompositeOperationXOR = 10,
  81. kCGCompositeOperationPlusDarker = 11,
  82. // NS only, unsupported by CG : Highlight
  83. kCGCompositeOperationPlusLighter = 12
  84. } CGCompositeOperation ;
  85. extern "C"
  86. {
  87. CG_EXTERN void CGContextSetCompositeOperation (CGContextRef context, int operation);
  88. } ;
  89. #endif
  90. //-----------------------------------------------------------------------------
  91. // constants
  92. //-----------------------------------------------------------------------------
  93. #if !defined( __DARWIN__ ) || defined(__MWERKS__)
  94. #ifndef M_PI
  95. const double M_PI = 3.14159265358979;
  96. #endif
  97. #endif
  98. static const double RAD2DEG = 180.0 / M_PI;
  99. //
  100. // Pen, Brushes and Fonts
  101. //
  102. #pragma mark -
  103. #pragma mark wxMacCoreGraphicsPattern, ImagePattern, HatchPattern classes
  104. OSStatus wxMacDrawCGImage(
  105. CGContextRef inContext,
  106. const CGRect * inBounds,
  107. CGImageRef inImage)
  108. {
  109. #if wxOSX_USE_CARBON
  110. return HIViewDrawCGImage( inContext, inBounds, inImage );
  111. #else
  112. CGContextSaveGState(inContext);
  113. CGContextTranslateCTM(inContext, inBounds->origin.x, inBounds->origin.y + inBounds->size.height);
  114. CGRect r = *inBounds;
  115. r.origin.x = r.origin.y = 0;
  116. CGContextScaleCTM(inContext, 1, -1);
  117. CGContextDrawImage(inContext, r, inImage );
  118. CGContextRestoreGState(inContext);
  119. return noErr;
  120. #endif
  121. }
  122. CGColorRef wxMacCreateCGColor( const wxColour& col )
  123. {
  124. CGColorRef retval = 0;
  125. #ifdef __WXMAC__
  126. retval = col.CreateCGColor();
  127. #else
  128. // TODO add conversion NSColor - CGColorRef (obj-c)
  129. #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
  130. if ( CGColorCreateGenericRGB )
  131. retval = CGColorCreateGenericRGB( col.Red() / 255.0 , col.Green() / 255.0, col.Blue() / 255.0, col.Alpha() / 255.0 );
  132. else
  133. #endif
  134. {
  135. CGFloat components[4] = { col.Red() / 255.0, col.Green() / 255.0, col.Blue() / 255.0, col.Alpha() / 255.0 } ;
  136. retval = CGColorCreate( wxMacGetGenericRGBColorSpace() , components ) ;
  137. }
  138. #endif
  139. return retval;
  140. }
  141. #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && wxOSX_USE_CORE_TEXT
  142. CTFontRef wxMacCreateCTFont( const wxFont& font )
  143. {
  144. #ifdef __WXMAC__
  145. return wxCFRetain((CTFontRef) font.OSXGetCTFont());
  146. #else
  147. return CTFontCreateWithName( wxCFStringRef( font.GetFaceName(), wxLocale::GetSystemEncoding() ) , font.GetPointSize() , NULL );
  148. #endif
  149. }
  150. #endif
  151. // CGPattern wrapper class: always allocate on heap, never call destructor
  152. class wxMacCoreGraphicsPattern
  153. {
  154. public :
  155. wxMacCoreGraphicsPattern() {}
  156. // is guaranteed to be called only with a non-Null CGContextRef
  157. virtual void Render( CGContextRef ctxRef ) = 0;
  158. operator CGPatternRef() const { return m_patternRef; }
  159. protected :
  160. virtual ~wxMacCoreGraphicsPattern()
  161. {
  162. // as this is called only when the m_patternRef is been released;
  163. // don't release it again
  164. }
  165. static void _Render( void *info, CGContextRef ctxRef )
  166. {
  167. wxMacCoreGraphicsPattern* self = (wxMacCoreGraphicsPattern*) info;
  168. if ( self && ctxRef )
  169. self->Render( ctxRef );
  170. }
  171. static void _Dispose( void *info )
  172. {
  173. wxMacCoreGraphicsPattern* self = (wxMacCoreGraphicsPattern*) info;
  174. delete self;
  175. }
  176. CGPatternRef m_patternRef;
  177. static const CGPatternCallbacks ms_Callbacks;
  178. };
  179. const CGPatternCallbacks wxMacCoreGraphicsPattern::ms_Callbacks = { 0, &wxMacCoreGraphicsPattern::_Render, &wxMacCoreGraphicsPattern::_Dispose };
  180. class ImagePattern : public wxMacCoreGraphicsPattern
  181. {
  182. public :
  183. ImagePattern( const wxBitmap* bmp , const CGAffineTransform& transform )
  184. {
  185. wxASSERT( bmp && bmp->IsOk() );
  186. #ifdef __WXMAC__
  187. Init( (CGImageRef) bmp->CreateCGImage() , transform );
  188. #endif
  189. }
  190. // ImagePattern takes ownership of CGImageRef passed in
  191. ImagePattern( CGImageRef image , const CGAffineTransform& transform )
  192. {
  193. if ( image )
  194. CFRetain( image );
  195. Init( image , transform );
  196. }
  197. virtual void Render( CGContextRef ctxRef )
  198. {
  199. if (m_image != NULL)
  200. wxMacDrawCGImage( ctxRef, &m_imageBounds, m_image );
  201. }
  202. protected :
  203. void Init( CGImageRef image, const CGAffineTransform& transform )
  204. {
  205. m_image = image;
  206. if ( m_image )
  207. {
  208. m_imageBounds = CGRectMake( (CGFloat) 0.0, (CGFloat) 0.0, (CGFloat)CGImageGetWidth( m_image ), (CGFloat)CGImageGetHeight( m_image ) );
  209. m_patternRef = CGPatternCreate(
  210. this , m_imageBounds, transform ,
  211. m_imageBounds.size.width, m_imageBounds.size.height,
  212. kCGPatternTilingNoDistortion, true , &wxMacCoreGraphicsPattern::ms_Callbacks );
  213. }
  214. }
  215. virtual ~ImagePattern()
  216. {
  217. if ( m_image )
  218. CGImageRelease( m_image );
  219. }
  220. CGImageRef m_image;
  221. CGRect m_imageBounds;
  222. };
  223. class HatchPattern : public wxMacCoreGraphicsPattern
  224. {
  225. public :
  226. HatchPattern( int hatchstyle, const CGAffineTransform& transform )
  227. {
  228. m_hatch = hatchstyle;
  229. m_imageBounds = CGRectMake( (CGFloat) 0.0, (CGFloat) 0.0, (CGFloat) 8.0 , (CGFloat) 8.0 );
  230. m_patternRef = CGPatternCreate(
  231. this , m_imageBounds, transform ,
  232. m_imageBounds.size.width, m_imageBounds.size.height,
  233. kCGPatternTilingNoDistortion, false , &wxMacCoreGraphicsPattern::ms_Callbacks );
  234. }
  235. void StrokeLineSegments( CGContextRef ctxRef , const CGPoint pts[] , size_t count )
  236. {
  237. CGContextStrokeLineSegments( ctxRef , pts , count );
  238. }
  239. virtual void Render( CGContextRef ctxRef )
  240. {
  241. switch ( m_hatch )
  242. {
  243. case wxBDIAGONAL_HATCH :
  244. {
  245. CGPoint pts[] =
  246. {
  247. { (CGFloat) 8.0 , (CGFloat) 0.0 } , { (CGFloat) 0.0 , (CGFloat) 8.0 }
  248. };
  249. StrokeLineSegments( ctxRef , pts , 2 );
  250. }
  251. break;
  252. case wxCROSSDIAG_HATCH :
  253. {
  254. CGPoint pts[] =
  255. {
  256. { (CGFloat) 0.0 , (CGFloat) 0.0 } , { (CGFloat) 8.0 , (CGFloat) 8.0 } ,
  257. { (CGFloat) 8.0 , (CGFloat) 0.0 } , { (CGFloat) 0.0 , (CGFloat) 8.0 }
  258. };
  259. StrokeLineSegments( ctxRef , pts , 4 );
  260. }
  261. break;
  262. case wxFDIAGONAL_HATCH :
  263. {
  264. CGPoint pts[] =
  265. {
  266. { (CGFloat) 0.0 , (CGFloat) 0.0 } , { (CGFloat) 8.0 , (CGFloat) 8.0 }
  267. };
  268. StrokeLineSegments( ctxRef , pts , 2 );
  269. }
  270. break;
  271. case wxCROSS_HATCH :
  272. {
  273. CGPoint pts[] =
  274. {
  275. { (CGFloat) 0.0 , (CGFloat) 4.0 } , { (CGFloat) 8.0 , (CGFloat) 4.0 } ,
  276. { (CGFloat) 4.0 , (CGFloat) 0.0 } , { (CGFloat) 4.0 , (CGFloat) 8.0 } ,
  277. };
  278. StrokeLineSegments( ctxRef , pts , 4 );
  279. }
  280. break;
  281. case wxHORIZONTAL_HATCH :
  282. {
  283. CGPoint pts[] =
  284. {
  285. { (CGFloat) 0.0 , (CGFloat) 4.0 } , { (CGFloat) 8.0 , (CGFloat) 4.0 } ,
  286. };
  287. StrokeLineSegments( ctxRef , pts , 2 );
  288. }
  289. break;
  290. case wxVERTICAL_HATCH :
  291. {
  292. CGPoint pts[] =
  293. {
  294. { (CGFloat) 4.0 , (CGFloat) 0.0 } , { (CGFloat) 4.0 , (CGFloat) 8.0 } ,
  295. };
  296. StrokeLineSegments( ctxRef , pts , 2 );
  297. }
  298. break;
  299. default:
  300. break;
  301. }
  302. }
  303. protected :
  304. virtual ~HatchPattern() {}
  305. CGRect m_imageBounds;
  306. int m_hatch;
  307. };
  308. class wxMacCoreGraphicsPenData : public wxGraphicsObjectRefData
  309. {
  310. public:
  311. wxMacCoreGraphicsPenData( wxGraphicsRenderer* renderer, const wxPen &pen );
  312. ~wxMacCoreGraphicsPenData();
  313. void Init();
  314. virtual void Apply( wxGraphicsContext* context );
  315. virtual wxDouble GetWidth() { return m_width; }
  316. protected :
  317. CGLineCap m_cap;
  318. wxCFRef<CGColorRef> m_color;
  319. wxCFRef<CGColorSpaceRef> m_colorSpace;
  320. CGLineJoin m_join;
  321. CGFloat m_width;
  322. int m_count;
  323. const CGFloat *m_lengths;
  324. CGFloat *m_userLengths;
  325. bool m_isPattern;
  326. wxCFRef<CGPatternRef> m_pattern;
  327. CGFloat* m_patternColorComponents;
  328. };
  329. wxMacCoreGraphicsPenData::wxMacCoreGraphicsPenData( wxGraphicsRenderer* renderer, const wxPen &pen ) :
  330. wxGraphicsObjectRefData( renderer )
  331. {
  332. Init();
  333. m_color.reset( wxMacCreateCGColor( pen.GetColour() ) ) ;
  334. // TODO: * m_dc->m_scaleX
  335. m_width = pen.GetWidth();
  336. if (m_width <= 0.0)
  337. m_width = (CGFloat) 0.1;
  338. switch ( pen.GetCap() )
  339. {
  340. case wxCAP_ROUND :
  341. m_cap = kCGLineCapRound;
  342. break;
  343. case wxCAP_PROJECTING :
  344. m_cap = kCGLineCapSquare;
  345. break;
  346. case wxCAP_BUTT :
  347. m_cap = kCGLineCapButt;
  348. break;
  349. default :
  350. m_cap = kCGLineCapButt;
  351. break;
  352. }
  353. switch ( pen.GetJoin() )
  354. {
  355. case wxJOIN_BEVEL :
  356. m_join = kCGLineJoinBevel;
  357. break;
  358. case wxJOIN_MITER :
  359. m_join = kCGLineJoinMiter;
  360. break;
  361. case wxJOIN_ROUND :
  362. m_join = kCGLineJoinRound;
  363. break;
  364. default :
  365. m_join = kCGLineJoinMiter;
  366. break;
  367. }
  368. const CGFloat dashUnit = m_width < 1.0 ? (CGFloat) 1.0 : m_width;
  369. const CGFloat dotted[] = { (CGFloat) dashUnit , (CGFloat) (dashUnit + 2.0) };
  370. static const CGFloat short_dashed[] = { (CGFloat) 9.0 , (CGFloat) 6.0 };
  371. static const CGFloat dashed[] = { (CGFloat) 19.0 , (CGFloat) 9.0 };
  372. static const CGFloat dotted_dashed[] = { (CGFloat) 9.0 , (CGFloat) 6.0 , (CGFloat) 3.0 , (CGFloat) 3.0 };
  373. switch ( pen.GetStyle() )
  374. {
  375. case wxPENSTYLE_SOLID:
  376. break;
  377. case wxPENSTYLE_DOT:
  378. m_count = WXSIZEOF(dotted);
  379. m_userLengths = new CGFloat[ m_count ] ;
  380. memcpy( m_userLengths, dotted, sizeof(dotted) );
  381. m_lengths = m_userLengths;
  382. break;
  383. case wxPENSTYLE_LONG_DASH:
  384. m_count = WXSIZEOF(dashed);
  385. m_lengths = dashed;
  386. break;
  387. case wxPENSTYLE_SHORT_DASH:
  388. m_count = WXSIZEOF(short_dashed);
  389. m_lengths = short_dashed;
  390. break;
  391. case wxPENSTYLE_DOT_DASH:
  392. m_count = WXSIZEOF(dotted_dashed);
  393. m_lengths = dotted_dashed;
  394. break;
  395. case wxPENSTYLE_USER_DASH:
  396. wxDash *dashes;
  397. m_count = pen.GetDashes( &dashes );
  398. if ((dashes != NULL) && (m_count > 0))
  399. {
  400. m_userLengths = new CGFloat[m_count];
  401. for ( int i = 0; i < m_count; ++i )
  402. {
  403. m_userLengths[i] = dashes[i] * dashUnit;
  404. if ( i % 2 == 1 && m_userLengths[i] < dashUnit + 2.0 )
  405. m_userLengths[i] = (CGFloat) (dashUnit + 2.0);
  406. else if ( i % 2 == 0 && m_userLengths[i] < dashUnit )
  407. m_userLengths[i] = dashUnit;
  408. }
  409. }
  410. m_lengths = m_userLengths;
  411. break;
  412. case wxPENSTYLE_STIPPLE:
  413. {
  414. wxBitmap* bmp = pen.GetStipple();
  415. if ( bmp && bmp->IsOk() )
  416. {
  417. m_colorSpace.reset( CGColorSpaceCreatePattern( NULL ) );
  418. m_pattern.reset( (CGPatternRef) *( new ImagePattern( bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) );
  419. m_patternColorComponents = new CGFloat[1] ;
  420. m_patternColorComponents[0] = (CGFloat) 1.0;
  421. m_isPattern = true;
  422. }
  423. }
  424. break;
  425. default :
  426. {
  427. m_isPattern = true;
  428. m_colorSpace.reset( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) );
  429. m_pattern.reset( (CGPatternRef) *( new HatchPattern( pen.GetStyle() , CGAffineTransformMakeScale( 1,-1 ) ) ) );
  430. m_patternColorComponents = new CGFloat[4] ;
  431. m_patternColorComponents[0] = (CGFloat) (pen.GetColour().Red() / 255.0);
  432. m_patternColorComponents[1] = (CGFloat) (pen.GetColour().Green() / 255.0);
  433. m_patternColorComponents[2] = (CGFloat) (pen.GetColour().Blue() / 255.0);
  434. m_patternColorComponents[3] = (CGFloat) (pen.GetColour().Alpha() / 255.0);
  435. }
  436. break;
  437. }
  438. if ((m_lengths != NULL) && (m_count > 0))
  439. {
  440. // force the line cap, otherwise we get artifacts (overlaps) and just solid lines
  441. m_cap = kCGLineCapButt;
  442. }
  443. }
  444. wxMacCoreGraphicsPenData::~wxMacCoreGraphicsPenData()
  445. {
  446. delete[] m_userLengths;
  447. delete[] m_patternColorComponents;
  448. }
  449. void wxMacCoreGraphicsPenData::Init()
  450. {
  451. m_lengths = NULL;
  452. m_userLengths = NULL;
  453. m_width = 0;
  454. m_count = 0;
  455. m_patternColorComponents = NULL;
  456. m_isPattern = false;
  457. }
  458. void wxMacCoreGraphicsPenData::Apply( wxGraphicsContext* context )
  459. {
  460. CGContextRef cg = (CGContextRef) context->GetNativeContext();
  461. CGContextSetLineWidth( cg , m_width );
  462. CGContextSetLineJoin( cg , m_join );
  463. CGContextSetLineDash( cg , 0 , m_lengths , m_count );
  464. CGContextSetLineCap( cg , m_cap );
  465. if ( m_isPattern )
  466. {
  467. CGAffineTransform matrix = CGContextGetCTM( cg );
  468. CGContextSetPatternPhase( cg, CGSizeMake(matrix.tx, matrix.ty) );
  469. CGContextSetStrokeColorSpace( cg , m_colorSpace );
  470. CGContextSetStrokePattern( cg, m_pattern , m_patternColorComponents );
  471. }
  472. else
  473. {
  474. CGContextSetStrokeColorWithColor( cg , m_color );
  475. }
  476. }
  477. //
  478. // Brush
  479. //
  480. // make sure we all use one class for all conversions from wx to native colour
  481. class wxMacCoreGraphicsColour
  482. {
  483. public:
  484. wxMacCoreGraphicsColour();
  485. wxMacCoreGraphicsColour(const wxBrush &brush);
  486. ~wxMacCoreGraphicsColour();
  487. void Apply( CGContextRef cgContext );
  488. protected:
  489. void Init();
  490. wxCFRef<CGColorRef> m_color;
  491. wxCFRef<CGColorSpaceRef> m_colorSpace;
  492. bool m_isPattern;
  493. wxCFRef<CGPatternRef> m_pattern;
  494. CGFloat* m_patternColorComponents;
  495. } ;
  496. wxMacCoreGraphicsColour::~wxMacCoreGraphicsColour()
  497. {
  498. delete[] m_patternColorComponents;
  499. }
  500. void wxMacCoreGraphicsColour::Init()
  501. {
  502. m_isPattern = false;
  503. m_patternColorComponents = NULL;
  504. }
  505. void wxMacCoreGraphicsColour::Apply( CGContextRef cgContext )
  506. {
  507. if ( m_isPattern )
  508. {
  509. CGAffineTransform matrix = CGContextGetCTM( cgContext );
  510. CGContextSetPatternPhase( cgContext, CGSizeMake(matrix.tx, matrix.ty) );
  511. CGContextSetFillColorSpace( cgContext , m_colorSpace );
  512. CGContextSetFillPattern( cgContext, m_pattern , m_patternColorComponents );
  513. }
  514. else
  515. {
  516. CGContextSetFillColorWithColor( cgContext, m_color );
  517. }
  518. }
  519. wxMacCoreGraphicsColour::wxMacCoreGraphicsColour()
  520. {
  521. Init();
  522. }
  523. wxMacCoreGraphicsColour::wxMacCoreGraphicsColour( const wxBrush &brush )
  524. {
  525. Init();
  526. if ( brush.GetStyle() == wxSOLID )
  527. {
  528. m_color.reset( wxMacCreateCGColor( brush.GetColour() ));
  529. }
  530. else if ( brush.IsHatch() )
  531. {
  532. m_isPattern = true;
  533. m_colorSpace.reset( CGColorSpaceCreatePattern( wxMacGetGenericRGBColorSpace() ) );
  534. m_pattern.reset( (CGPatternRef) *( new HatchPattern( brush.GetStyle() , CGAffineTransformMakeScale( 1,-1 ) ) ) );
  535. m_patternColorComponents = new CGFloat[4] ;
  536. m_patternColorComponents[0] = (CGFloat) (brush.GetColour().Red() / 255.0);
  537. m_patternColorComponents[1] = (CGFloat) (brush.GetColour().Green() / 255.0);
  538. m_patternColorComponents[2] = (CGFloat) (brush.GetColour().Blue() / 255.0);
  539. m_patternColorComponents[3] = (CGFloat) (brush.GetColour().Alpha() / 255.0);
  540. }
  541. else
  542. {
  543. // now brush is a bitmap
  544. wxBitmap* bmp = brush.GetStipple();
  545. if ( bmp && bmp->IsOk() )
  546. {
  547. m_isPattern = true;
  548. m_patternColorComponents = new CGFloat[1] ;
  549. m_patternColorComponents[0] = (CGFloat) 1.0;
  550. m_colorSpace.reset( CGColorSpaceCreatePattern( NULL ) );
  551. m_pattern.reset( (CGPatternRef) *( new ImagePattern( bmp , CGAffineTransformMakeScale( 1,-1 ) ) ) );
  552. }
  553. }
  554. }
  555. class wxMacCoreGraphicsBrushData : public wxGraphicsObjectRefData
  556. {
  557. public:
  558. wxMacCoreGraphicsBrushData( wxGraphicsRenderer* renderer );
  559. wxMacCoreGraphicsBrushData( wxGraphicsRenderer* renderer, const wxBrush &brush );
  560. ~wxMacCoreGraphicsBrushData ();
  561. virtual void Apply( wxGraphicsContext* context );
  562. void CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
  563. wxDouble x2, wxDouble y2,
  564. const wxGraphicsGradientStops& stops);
  565. void CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
  566. wxDouble xc, wxDouble yc, wxDouble radius,
  567. const wxGraphicsGradientStops& stops);
  568. virtual bool IsShading() { return m_isShading; }
  569. CGShadingRef GetShading() { return m_shading; }
  570. protected:
  571. CGFunctionRef CreateGradientFunction(const wxGraphicsGradientStops& stops);
  572. static void CalculateShadingValues (void *info, const CGFloat *in, CGFloat *out);
  573. virtual void Init();
  574. wxMacCoreGraphicsColour m_cgColor;
  575. bool m_isShading;
  576. CGFunctionRef m_gradientFunction;
  577. CGShadingRef m_shading;
  578. // information about a single gradient component
  579. struct GradientComponent
  580. {
  581. CGFloat pos;
  582. CGFloat red;
  583. CGFloat green;
  584. CGFloat blue;
  585. CGFloat alpha;
  586. };
  587. // and information about all of them
  588. struct GradientComponents
  589. {
  590. GradientComponents()
  591. {
  592. count = 0;
  593. comps = NULL;
  594. }
  595. void Init(unsigned count_)
  596. {
  597. count = count_;
  598. comps = new GradientComponent[count];
  599. }
  600. ~GradientComponents()
  601. {
  602. delete [] comps;
  603. }
  604. unsigned count;
  605. GradientComponent *comps;
  606. };
  607. GradientComponents m_gradientComponents;
  608. };
  609. wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData( wxGraphicsRenderer* renderer) : wxGraphicsObjectRefData( renderer )
  610. {
  611. Init();
  612. }
  613. void
  614. wxMacCoreGraphicsBrushData::CreateLinearGradientBrush(wxDouble x1, wxDouble y1,
  615. wxDouble x2, wxDouble y2,
  616. const wxGraphicsGradientStops& stops)
  617. {
  618. m_gradientFunction = CreateGradientFunction(stops);
  619. m_shading = CGShadingCreateAxial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat) x1, (CGFloat) y1),
  620. CGPointMake((CGFloat) x2,(CGFloat) y2), m_gradientFunction, true, true ) ;
  621. m_isShading = true ;
  622. }
  623. void
  624. wxMacCoreGraphicsBrushData::CreateRadialGradientBrush(wxDouble xo, wxDouble yo,
  625. wxDouble xc, wxDouble yc,
  626. wxDouble radius,
  627. const wxGraphicsGradientStops& stops)
  628. {
  629. m_gradientFunction = CreateGradientFunction(stops);
  630. m_shading = CGShadingCreateRadial( wxMacGetGenericRGBColorSpace(), CGPointMake((CGFloat) xo,(CGFloat) yo), 0,
  631. CGPointMake((CGFloat) xc,(CGFloat) yc), (CGFloat) radius, m_gradientFunction, true, true ) ;
  632. m_isShading = true ;
  633. }
  634. wxMacCoreGraphicsBrushData::wxMacCoreGraphicsBrushData(wxGraphicsRenderer* renderer, const wxBrush &brush) : wxGraphicsObjectRefData( renderer ),
  635. m_cgColor( brush )
  636. {
  637. Init();
  638. }
  639. wxMacCoreGraphicsBrushData::~wxMacCoreGraphicsBrushData()
  640. {
  641. if ( m_shading )
  642. CGShadingRelease(m_shading);
  643. if( m_gradientFunction )
  644. CGFunctionRelease(m_gradientFunction);
  645. }
  646. void wxMacCoreGraphicsBrushData::Init()
  647. {
  648. m_gradientFunction = NULL;
  649. m_shading = NULL;
  650. m_isShading = false;
  651. }
  652. void wxMacCoreGraphicsBrushData::Apply( wxGraphicsContext* context )
  653. {
  654. CGContextRef cg = (CGContextRef) context->GetNativeContext();
  655. if ( m_isShading )
  656. {
  657. // nothing to set as shades are processed by clipping using the path and filling
  658. }
  659. else
  660. {
  661. m_cgColor.Apply( cg );
  662. }
  663. }
  664. void wxMacCoreGraphicsBrushData::CalculateShadingValues (void *info, const CGFloat *in, CGFloat *out)
  665. {
  666. const GradientComponents& stops = *(GradientComponents*) info ;
  667. CGFloat f = *in;
  668. if (f <= 0.0)
  669. {
  670. // Start
  671. out[0] = stops.comps[0].red;
  672. out[1] = stops.comps[0].green;
  673. out[2] = stops.comps[0].blue;
  674. out[3] = stops.comps[0].alpha;
  675. }
  676. else if (f >= 1.0)
  677. {
  678. // end
  679. out[0] = stops.comps[stops.count - 1].red;
  680. out[1] = stops.comps[stops.count - 1].green;
  681. out[2] = stops.comps[stops.count - 1].blue;
  682. out[3] = stops.comps[stops.count - 1].alpha;
  683. }
  684. else
  685. {
  686. // Find first component with position greater than f
  687. unsigned i;
  688. for ( i = 0; i < stops.count; i++ )
  689. {
  690. if (stops.comps[i].pos > f)
  691. break;
  692. }
  693. // Interpolated between stops
  694. CGFloat diff = (f - stops.comps[i-1].pos);
  695. CGFloat range = (stops.comps[i].pos - stops.comps[i-1].pos);
  696. CGFloat fact = diff / range;
  697. out[0] = stops.comps[i - 1].red + (stops.comps[i].red - stops.comps[i - 1].red) * fact;
  698. out[1] = stops.comps[i - 1].green + (stops.comps[i].green - stops.comps[i - 1].green) * fact;
  699. out[2] = stops.comps[i - 1].blue + (stops.comps[i].blue - stops.comps[i - 1].blue) * fact;
  700. out[3] = stops.comps[i - 1].alpha + (stops.comps[i].alpha - stops.comps[i - 1].alpha) * fact;
  701. }
  702. }
  703. CGFunctionRef
  704. wxMacCoreGraphicsBrushData::CreateGradientFunction(const wxGraphicsGradientStops& stops)
  705. {
  706. static const CGFunctionCallbacks callbacks = { 0, &CalculateShadingValues, NULL };
  707. static const CGFloat input_value_range [2] = { 0, 1 };
  708. static const CGFloat output_value_ranges [8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
  709. m_gradientComponents.Init(stops.GetCount());
  710. for ( unsigned i = 0; i < m_gradientComponents.count; i++ )
  711. {
  712. const wxGraphicsGradientStop stop = stops.Item(i);
  713. m_gradientComponents.comps[i].pos = stop.GetPosition();
  714. const wxColour col = stop.GetColour();
  715. m_gradientComponents.comps[i].red = (CGFloat) (col.Red() / 255.0);
  716. m_gradientComponents.comps[i].green = (CGFloat) (col.Green() / 255.0);
  717. m_gradientComponents.comps[i].blue = (CGFloat) (col.Blue() / 255.0);
  718. m_gradientComponents.comps[i].alpha = (CGFloat) (col.Alpha() / 255.0);
  719. }
  720. return CGFunctionCreate ( &m_gradientComponents, 1,
  721. input_value_range,
  722. 4,
  723. output_value_ranges,
  724. &callbacks);
  725. }
  726. //
  727. // Font
  728. //
  729. #if wxOSX_USE_IPHONE
  730. extern UIFont* CreateUIFont( const wxFont& font );
  731. extern void DrawTextInContext( CGContextRef context, CGPoint where, UIFont *font, NSString* text );
  732. extern CGSize MeasureTextInContext( UIFont *font, NSString* text );
  733. #endif
  734. class wxMacCoreGraphicsFontData : public wxGraphicsObjectRefData
  735. {
  736. public:
  737. wxMacCoreGraphicsFontData( wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col );
  738. ~wxMacCoreGraphicsFontData();
  739. #if wxOSX_USE_ATSU_TEXT
  740. virtual ATSUStyle GetATSUStyle() { return m_macATSUIStyle; }
  741. #endif
  742. #if wxOSX_USE_CORE_TEXT
  743. CTFontRef OSXGetCTFont() const { return m_ctFont ; }
  744. #endif
  745. wxColour GetColour() const { return m_colour ; }
  746. bool GetUnderlined() const { return m_underlined ; }
  747. #if wxOSX_USE_IPHONE
  748. UIFont* GetUIFont() const { return m_uiFont; }
  749. #endif
  750. private :
  751. wxColour m_colour;
  752. bool m_underlined;
  753. #if wxOSX_USE_ATSU_TEXT
  754. ATSUStyle m_macATSUIStyle;
  755. #endif
  756. #if wxOSX_USE_CORE_TEXT
  757. wxCFRef< CTFontRef > m_ctFont;
  758. #endif
  759. #if wxOSX_USE_IPHONE
  760. UIFont* m_uiFont;
  761. #endif
  762. };
  763. wxMacCoreGraphicsFontData::wxMacCoreGraphicsFontData(wxGraphicsRenderer* renderer, const wxFont &font, const wxColour& col) : wxGraphicsObjectRefData( renderer )
  764. {
  765. m_colour = col;
  766. m_underlined = font.GetUnderlined();
  767. #if wxOSX_USE_CORE_TEXT
  768. m_ctFont.reset( wxMacCreateCTFont( font ) );
  769. #endif
  770. #if wxOSX_USE_IPHONE
  771. m_uiFont = CreateUIFont(font);
  772. wxMacCocoaRetain( m_uiFont );
  773. #endif
  774. #if wxOSX_USE_ATSU_TEXT
  775. OSStatus status = noErr;
  776. m_macATSUIStyle = NULL;
  777. status = ATSUCreateAndCopyStyle( (ATSUStyle) font.MacGetATSUStyle() , &m_macATSUIStyle );
  778. wxASSERT_MSG( status == noErr, wxT("couldn't create ATSU style") );
  779. // we need the scale here ...
  780. Fixed atsuSize = IntToFixed( int( 1 * font.GetPointSize()) );
  781. RGBColor atsuColor ;
  782. col.GetRGBColor( &atsuColor );
  783. ATSUAttributeTag atsuTags[] =
  784. {
  785. kATSUSizeTag ,
  786. kATSUColorTag ,
  787. };
  788. ByteCount atsuSizes[WXSIZEOF(atsuTags)] =
  789. {
  790. sizeof( Fixed ) ,
  791. sizeof( RGBColor ) ,
  792. };
  793. ATSUAttributeValuePtr atsuValues[WXSIZEOF(atsuTags)] =
  794. {
  795. &atsuSize ,
  796. &atsuColor ,
  797. };
  798. status = ::ATSUSetAttributes(
  799. m_macATSUIStyle, WXSIZEOF(atsuTags),
  800. atsuTags, atsuSizes, atsuValues);
  801. wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") );
  802. #endif
  803. }
  804. wxMacCoreGraphicsFontData::~wxMacCoreGraphicsFontData()
  805. {
  806. #if wxOSX_USE_CORE_TEXT
  807. #endif
  808. #if wxOSX_USE_ATSU_TEXT
  809. if ( m_macATSUIStyle )
  810. {
  811. ::ATSUDisposeStyle((ATSUStyle)m_macATSUIStyle);
  812. m_macATSUIStyle = NULL;
  813. }
  814. #endif
  815. #if wxOSX_USE_IPHONE
  816. wxMacCocoaRelease( m_uiFont );
  817. #endif
  818. }
  819. class wxMacCoreGraphicsBitmapData : public wxGraphicsObjectRefData
  820. {
  821. public:
  822. wxMacCoreGraphicsBitmapData( wxGraphicsRenderer* renderer, CGImageRef bitmap, bool monochrome );
  823. ~wxMacCoreGraphicsBitmapData();
  824. virtual CGImageRef GetBitmap() { return m_bitmap; }
  825. bool IsMonochrome() { return m_monochrome; }
  826. private :
  827. CGImageRef m_bitmap;
  828. bool m_monochrome;
  829. };
  830. wxMacCoreGraphicsBitmapData::wxMacCoreGraphicsBitmapData( wxGraphicsRenderer* renderer, CGImageRef bitmap, bool monochrome ) : wxGraphicsObjectRefData( renderer ),
  831. m_bitmap(bitmap), m_monochrome(monochrome)
  832. {
  833. }
  834. wxMacCoreGraphicsBitmapData::~wxMacCoreGraphicsBitmapData()
  835. {
  836. CGImageRelease( m_bitmap );
  837. }
  838. //
  839. // Graphics Matrix
  840. //
  841. //-----------------------------------------------------------------------------
  842. // wxMacCoreGraphicsMatrix declaration
  843. //-----------------------------------------------------------------------------
  844. class WXDLLIMPEXP_CORE wxMacCoreGraphicsMatrixData : public wxGraphicsMatrixData
  845. {
  846. public :
  847. wxMacCoreGraphicsMatrixData(wxGraphicsRenderer* renderer) ;
  848. virtual ~wxMacCoreGraphicsMatrixData() ;
  849. virtual wxGraphicsObjectRefData *Clone() const ;
  850. // concatenates the matrix
  851. virtual void Concat( const wxGraphicsMatrixData *t );
  852. // sets the matrix to the respective values
  853. virtual void Set(wxDouble a=1.0, wxDouble b=0.0, wxDouble c=0.0, wxDouble d=1.0,
  854. wxDouble tx=0.0, wxDouble ty=0.0);
  855. // gets the component valuess of the matrix
  856. virtual void Get(wxDouble* a=NULL, wxDouble* b=NULL, wxDouble* c=NULL,
  857. wxDouble* d=NULL, wxDouble* tx=NULL, wxDouble* ty=NULL) const;
  858. // makes this the inverse matrix
  859. virtual void Invert();
  860. // returns true if the elements of the transformation matrix are equal ?
  861. virtual bool IsEqual( const wxGraphicsMatrixData* t) const ;
  862. // return true if this is the identity matrix
  863. virtual bool IsIdentity() const;
  864. //
  865. // transformation
  866. //
  867. // add the translation to this matrix
  868. virtual void Translate( wxDouble dx , wxDouble dy );
  869. // add the scale to this matrix
  870. virtual void Scale( wxDouble xScale , wxDouble yScale );
  871. // add the rotation to this matrix (radians)
  872. virtual void Rotate( wxDouble angle );
  873. //
  874. // apply the transforms
  875. //
  876. // applies that matrix to the point
  877. virtual void TransformPoint( wxDouble *x, wxDouble *y ) const;
  878. // applies the matrix except for translations
  879. virtual void TransformDistance( wxDouble *dx, wxDouble *dy ) const;
  880. // returns the native representation
  881. virtual void * GetNativeMatrix() const;
  882. private :
  883. CGAffineTransform m_matrix;
  884. } ;
  885. //-----------------------------------------------------------------------------
  886. // wxMacCoreGraphicsMatrix implementation
  887. //-----------------------------------------------------------------------------
  888. wxMacCoreGraphicsMatrixData::wxMacCoreGraphicsMatrixData(wxGraphicsRenderer* renderer) : wxGraphicsMatrixData(renderer)
  889. {
  890. }
  891. wxMacCoreGraphicsMatrixData::~wxMacCoreGraphicsMatrixData()
  892. {
  893. }
  894. wxGraphicsObjectRefData *wxMacCoreGraphicsMatrixData::Clone() const
  895. {
  896. wxMacCoreGraphicsMatrixData* m = new wxMacCoreGraphicsMatrixData(GetRenderer()) ;
  897. m->m_matrix = m_matrix ;
  898. return m;
  899. }
  900. // concatenates the matrix
  901. void wxMacCoreGraphicsMatrixData::Concat( const wxGraphicsMatrixData *t )
  902. {
  903. m_matrix = CGAffineTransformConcat(*((CGAffineTransform*) t->GetNativeMatrix()), m_matrix );
  904. }
  905. // sets the matrix to the respective values
  906. void wxMacCoreGraphicsMatrixData::Set(wxDouble a, wxDouble b, wxDouble c, wxDouble d,
  907. wxDouble tx, wxDouble ty)
  908. {
  909. m_matrix = CGAffineTransformMake((CGFloat) a,(CGFloat) b,(CGFloat) c,(CGFloat) d,(CGFloat) tx,(CGFloat) ty);
  910. }
  911. // gets the component valuess of the matrix
  912. void wxMacCoreGraphicsMatrixData::Get(wxDouble* a, wxDouble* b, wxDouble* c,
  913. wxDouble* d, wxDouble* tx, wxDouble* ty) const
  914. {
  915. if (a) *a = m_matrix.a;
  916. if (b) *b = m_matrix.b;
  917. if (c) *c = m_matrix.c;
  918. if (d) *d = m_matrix.d;
  919. if (tx) *tx= m_matrix.tx;
  920. if (ty) *ty= m_matrix.ty;
  921. }
  922. // makes this the inverse matrix
  923. void wxMacCoreGraphicsMatrixData::Invert()
  924. {
  925. m_matrix = CGAffineTransformInvert( m_matrix );
  926. }
  927. // returns true if the elements of the transformation matrix are equal ?
  928. bool wxMacCoreGraphicsMatrixData::IsEqual( const wxGraphicsMatrixData* t) const
  929. {
  930. return CGAffineTransformEqualToTransform(m_matrix, *((CGAffineTransform*) t->GetNativeMatrix()));
  931. }
  932. // return true if this is the identity matrix
  933. bool wxMacCoreGraphicsMatrixData::IsIdentity() const
  934. {
  935. return ( m_matrix.a == 1 && m_matrix.d == 1 &&
  936. m_matrix.b == 0 && m_matrix.d == 0 && m_matrix.tx == 0 && m_matrix.ty == 0);
  937. }
  938. //
  939. // transformation
  940. //
  941. // add the translation to this matrix
  942. void wxMacCoreGraphicsMatrixData::Translate( wxDouble dx , wxDouble dy )
  943. {
  944. m_matrix = CGAffineTransformTranslate( m_matrix, (CGFloat) dx, (CGFloat) dy);
  945. }
  946. // add the scale to this matrix
  947. void wxMacCoreGraphicsMatrixData::Scale( wxDouble xScale , wxDouble yScale )
  948. {
  949. m_matrix = CGAffineTransformScale( m_matrix, (CGFloat) xScale, (CGFloat) yScale);
  950. }
  951. // add the rotation to this matrix (radians)
  952. void wxMacCoreGraphicsMatrixData::Rotate( wxDouble angle )
  953. {
  954. m_matrix = CGAffineTransformRotate( m_matrix, (CGFloat) angle);
  955. }
  956. //
  957. // apply the transforms
  958. //
  959. // applies that matrix to the point
  960. void wxMacCoreGraphicsMatrixData::TransformPoint( wxDouble *x, wxDouble *y ) const
  961. {
  962. CGPoint pt = CGPointApplyAffineTransform( CGPointMake((CGFloat) *x,(CGFloat) *y), m_matrix);
  963. *x = pt.x;
  964. *y = pt.y;
  965. }
  966. // applies the matrix except for translations
  967. void wxMacCoreGraphicsMatrixData::TransformDistance( wxDouble *dx, wxDouble *dy ) const
  968. {
  969. CGSize sz = CGSizeApplyAffineTransform( CGSizeMake((CGFloat) *dx,(CGFloat) *dy) , m_matrix );
  970. *dx = sz.width;
  971. *dy = sz.height;
  972. }
  973. // returns the native representation
  974. void * wxMacCoreGraphicsMatrixData::GetNativeMatrix() const
  975. {
  976. return (void*) &m_matrix;
  977. }
  978. //
  979. // Graphics Path
  980. //
  981. //-----------------------------------------------------------------------------
  982. // wxMacCoreGraphicsPath declaration
  983. //-----------------------------------------------------------------------------
  984. class WXDLLEXPORT wxMacCoreGraphicsPathData : public wxGraphicsPathData
  985. {
  986. public :
  987. wxMacCoreGraphicsPathData( wxGraphicsRenderer* renderer, CGMutablePathRef path = NULL);
  988. ~wxMacCoreGraphicsPathData();
  989. virtual wxGraphicsObjectRefData *Clone() const;
  990. // begins a new subpath at (x,y)
  991. virtual void MoveToPoint( wxDouble x, wxDouble y );
  992. // adds a straight line from the current point to (x,y)
  993. virtual void AddLineToPoint( wxDouble x, wxDouble y );
  994. // adds a cubic Bezier curve from the current point, using two control points and an end point
  995. virtual void AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y );
  996. // closes the current sub-path
  997. virtual void CloseSubpath();
  998. // gets the last point of the current path, (0,0) if not yet set
  999. virtual void GetCurrentPoint( wxDouble* x, wxDouble* y) const;
  1000. // adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
  1001. virtual void AddArc( wxDouble x, wxDouble y, wxDouble r, wxDouble startAngle, wxDouble endAngle, bool clockwise );
  1002. //
  1003. // These are convenience functions which - if not available natively will be assembled
  1004. // using the primitives from above
  1005. //
  1006. // adds a quadratic Bezier curve from the current point, using a control point and an end point
  1007. virtual void AddQuadCurveToPoint( wxDouble cx, wxDouble cy, wxDouble x, wxDouble y );
  1008. // appends a rectangle as a new closed subpath
  1009. virtual void AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h );
  1010. // appends a circle as a new closed subpath
  1011. virtual void AddCircle( wxDouble x, wxDouble y, wxDouble r );
  1012. // appends an ellipsis as a new closed subpath fitting the passed rectangle
  1013. virtual void AddEllipse( wxDouble x, wxDouble y, wxDouble w, wxDouble h);
  1014. // draws a an arc to two tangents connecting (current) to (x1,y1) and (x1,y1) to (x2,y2), also a straight line from (current) to (x1,y1)
  1015. virtual void AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r );
  1016. // adds another path
  1017. virtual void AddPath( const wxGraphicsPathData* path );
  1018. // returns the native path
  1019. virtual void * GetNativePath() const { return m_path; }
  1020. // give the native path returned by GetNativePath() back (there might be some deallocations necessary)
  1021. virtual void UnGetNativePath(void *WXUNUSED(p)) const {}
  1022. // transforms each point of this path by the matrix
  1023. virtual void Transform( const wxGraphicsMatrixData* matrix );
  1024. // gets the bounding box enclosing all points (possibly including control points)
  1025. virtual void GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) const;
  1026. virtual bool Contains( wxDouble x, wxDouble y, wxPolygonFillMode fillStyle = wxODDEVEN_RULE) const;
  1027. private :
  1028. CGMutablePathRef m_path;
  1029. };
  1030. //-----------------------------------------------------------------------------
  1031. // wxMacCoreGraphicsPath implementation
  1032. //-----------------------------------------------------------------------------
  1033. wxMacCoreGraphicsPathData::wxMacCoreGraphicsPathData( wxGraphicsRenderer* renderer, CGMutablePathRef path) : wxGraphicsPathData(renderer)
  1034. {
  1035. if ( path )
  1036. m_path = path;
  1037. else
  1038. m_path = CGPathCreateMutable();
  1039. }
  1040. wxMacCoreGraphicsPathData::~wxMacCoreGraphicsPathData()
  1041. {
  1042. CGPathRelease( m_path );
  1043. }
  1044. wxGraphicsObjectRefData* wxMacCoreGraphicsPathData::Clone() const
  1045. {
  1046. wxMacCoreGraphicsPathData* clone = new wxMacCoreGraphicsPathData(GetRenderer(),CGPathCreateMutableCopy(m_path));
  1047. return clone ;
  1048. }
  1049. // opens (starts) a new subpath
  1050. void wxMacCoreGraphicsPathData::MoveToPoint( wxDouble x1 , wxDouble y1 )
  1051. {
  1052. CGPathMoveToPoint( m_path , NULL , (CGFloat) x1 , (CGFloat) y1 );
  1053. }
  1054. void wxMacCoreGraphicsPathData::AddLineToPoint( wxDouble x1 , wxDouble y1 )
  1055. {
  1056. CGPathAddLineToPoint( m_path , NULL , (CGFloat) x1 , (CGFloat) y1 );
  1057. }
  1058. void wxMacCoreGraphicsPathData::AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y )
  1059. {
  1060. CGPathAddCurveToPoint( m_path , NULL , (CGFloat) cx1 , (CGFloat) cy1 , (CGFloat) cx2, (CGFloat) cy2, (CGFloat) x , (CGFloat) y );
  1061. }
  1062. void wxMacCoreGraphicsPathData::AddQuadCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble x, wxDouble y )
  1063. {
  1064. CGPathAddQuadCurveToPoint( m_path , NULL , (CGFloat) cx1 , (CGFloat) cy1 , (CGFloat) x , (CGFloat) y );
  1065. }
  1066. void wxMacCoreGraphicsPathData::AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
  1067. {
  1068. CGRect cgRect = { { (CGFloat) x , (CGFloat) y } , { (CGFloat) w , (CGFloat) h } };
  1069. CGPathAddRect( m_path , NULL , cgRect );
  1070. }
  1071. void wxMacCoreGraphicsPathData::AddCircle( wxDouble x, wxDouble y , wxDouble r )
  1072. {
  1073. CGPathAddEllipseInRect( m_path, NULL, CGRectMake(x-r,y-r,2*r,2*r));
  1074. }
  1075. void wxMacCoreGraphicsPathData::AddEllipse( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
  1076. {
  1077. CGPathAddEllipseInRect( m_path, NULL, CGRectMake(x,y,w,h));
  1078. }
  1079. // adds an arc of a circle centering at (x,y) with radius (r) from startAngle to endAngle
  1080. void wxMacCoreGraphicsPathData::AddArc( wxDouble x, wxDouble y, wxDouble r, wxDouble startAngle, wxDouble endAngle, bool clockwise )
  1081. {
  1082. // inverse direction as we the 'normal' state is a y axis pointing down, ie mirrored to the standard core graphics setup
  1083. CGPathAddArc( m_path, NULL , (CGFloat) x, (CGFloat) y, (CGFloat) r, (CGFloat) startAngle, (CGFloat) endAngle, !clockwise);
  1084. }
  1085. void wxMacCoreGraphicsPathData::AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r )
  1086. {
  1087. CGPathAddArcToPoint( m_path, NULL , (CGFloat) x1, (CGFloat) y1, (CGFloat) x2, (CGFloat) y2, (CGFloat) r);
  1088. }
  1089. void wxMacCoreGraphicsPathData::AddPath( const wxGraphicsPathData* path )
  1090. {
  1091. CGPathAddPath( m_path , NULL, (CGPathRef) path->GetNativePath() );
  1092. }
  1093. // closes the current subpath
  1094. void wxMacCoreGraphicsPathData::CloseSubpath()
  1095. {
  1096. CGPathCloseSubpath( m_path );
  1097. }
  1098. // gets the last point of the current path, (0,0) if not yet set
  1099. void wxMacCoreGraphicsPathData::GetCurrentPoint( wxDouble* x, wxDouble* y) const
  1100. {
  1101. CGPoint p = CGPathGetCurrentPoint( m_path );
  1102. *x = p.x;
  1103. *y = p.y;
  1104. }
  1105. // transforms each point of this path by the matrix
  1106. void wxMacCoreGraphicsPathData::Transform( const wxGraphicsMatrixData* matrix )
  1107. {
  1108. CGMutablePathRef p = CGPathCreateMutable() ;
  1109. CGPathAddPath( p, (CGAffineTransform*) matrix->GetNativeMatrix() , m_path );
  1110. CGPathRelease( m_path );
  1111. m_path = p;
  1112. }
  1113. // gets the bounding box enclosing all points (possibly including control points)
  1114. void wxMacCoreGraphicsPathData::GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) const
  1115. {
  1116. CGRect bounds = CGPathGetBoundingBox( m_path ) ;
  1117. *x = bounds.origin.x;
  1118. *y = bounds.origin.y;
  1119. *w = bounds.size.width;
  1120. *h = bounds.size.height;
  1121. }
  1122. bool wxMacCoreGraphicsPathData::Contains( wxDouble x, wxDouble y, wxPolygonFillMode fillStyle) const
  1123. {
  1124. return CGPathContainsPoint( m_path, NULL, CGPointMake((CGFloat) x,(CGFloat) y), fillStyle == wxODDEVEN_RULE );
  1125. }
  1126. //
  1127. // Graphics Context
  1128. //
  1129. //-----------------------------------------------------------------------------
  1130. // wxMacCoreGraphicsContext declaration
  1131. //-----------------------------------------------------------------------------
  1132. class WXDLLEXPORT wxMacCoreGraphicsContext : public wxGraphicsContext
  1133. {
  1134. public:
  1135. wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext, wxDouble width = 0, wxDouble height = 0 );
  1136. #if wxOSX_USE_CARBON
  1137. wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, WindowRef window );
  1138. #endif
  1139. wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, wxWindow* window );
  1140. wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer);
  1141. wxMacCoreGraphicsContext();
  1142. ~wxMacCoreGraphicsContext();
  1143. void Init();
  1144. virtual void StartPage( wxDouble width, wxDouble height );
  1145. virtual void EndPage();
  1146. virtual void Flush();
  1147. // push the current state of the context, ie the transformation matrix on a stack
  1148. virtual void PushState();
  1149. // pops a stored state from the stack
  1150. virtual void PopState();
  1151. // clips drawings to the region
  1152. virtual void Clip( const wxRegion &region );
  1153. // clips drawings to the rect
  1154. virtual void Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h );
  1155. // resets the clipping to original extent
  1156. virtual void ResetClip();
  1157. virtual void * GetNativeContext();
  1158. virtual bool SetAntialiasMode(wxAntialiasMode antialias);
  1159. virtual bool SetInterpolationQuality(wxInterpolationQuality interpolation);
  1160. virtual bool SetCompositionMode(wxCompositionMode op);
  1161. virtual void BeginLayer(wxDouble opacity);
  1162. virtual void EndLayer();
  1163. //
  1164. // transformation
  1165. //
  1166. // translate
  1167. virtual void Translate( wxDouble dx , wxDouble dy );
  1168. // scale
  1169. virtual void Scale( wxDouble xScale , wxDouble yScale );
  1170. // rotate (radians)
  1171. virtual void Rotate( wxDouble angle );
  1172. // concatenates this transform with the current transform of this context
  1173. virtual void ConcatTransform( const wxGraphicsMatrix& matrix );
  1174. // sets the transform of this context
  1175. virtual void SetTransform( const wxGraphicsMatrix& matrix );
  1176. // gets the matrix of this context
  1177. virtual wxGraphicsMatrix GetTransform() const;
  1178. //
  1179. // setting the paint
  1180. //
  1181. // strokes along a path with the current pen
  1182. virtual void StrokePath( const wxGraphicsPath &path );
  1183. // fills a path with the current brush
  1184. virtual void FillPath( const wxGraphicsPath &path, wxPolygonFillMode fillStyle = wxODDEVEN_RULE );
  1185. // draws a path by first filling and then stroking
  1186. virtual void DrawPath( const wxGraphicsPath &path, wxPolygonFillMode fillStyle = wxODDEVEN_RULE );
  1187. virtual bool ShouldOffset() const
  1188. {
  1189. if ( !m_enableOffset )
  1190. return false;
  1191. int penwidth = 0 ;
  1192. if ( !m_pen.IsNull() )
  1193. {
  1194. penwidth = (int)((wxMacCoreGraphicsPenData*)m_pen.GetRefData())->GetWidth();
  1195. if ( penwidth == 0 )
  1196. penwidth = 1;
  1197. }
  1198. return ( penwidth % 2 ) == 1;
  1199. }
  1200. //
  1201. // text
  1202. //
  1203. virtual void GetTextExtent( const wxString &text, wxDouble *width, wxDouble *height,
  1204. wxDouble *descent, wxDouble *externalLeading ) const;
  1205. virtual void GetPartialTextExtents(const wxString& text, wxArrayDouble& widths) const;
  1206. //
  1207. // image support
  1208. //
  1209. virtual void DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
  1210. virtual void DrawBitmap( const wxGraphicsBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
  1211. virtual void DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h );
  1212. // fast convenience methods
  1213. virtual void DrawRectangleX( wxDouble x, wxDouble y, wxDouble w, wxDouble h );
  1214. void SetNativeContext( CGContextRef cg );
  1215. DECLARE_DYNAMIC_CLASS_NO_COPY(wxMacCoreGraphicsContext)
  1216. private:
  1217. bool EnsureIsValid();
  1218. virtual void DoDrawText( const wxString &str, wxDouble x, wxDouble y );
  1219. virtual void DoDrawRotatedText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle );
  1220. CGContextRef m_cgContext;
  1221. #if wxOSX_USE_CARBON
  1222. WindowRef m_windowRef;
  1223. #else
  1224. WXWidget m_view;
  1225. #endif
  1226. bool m_contextSynthesized;
  1227. CGAffineTransform m_windowTransform;
  1228. bool m_invisible;
  1229. #if wxOSX_USE_COCOA_OR_CARBON
  1230. wxCFRef<HIShapeRef> m_clipRgn;
  1231. #endif
  1232. };
  1233. //-----------------------------------------------------------------------------
  1234. // device context implementation
  1235. //
  1236. // more and more of the dc functionality should be implemented by calling
  1237. // the appropricate wxMacCoreGraphicsContext, but we will have to do that step by step
  1238. // also coordinate conversions should be moved to native matrix ops
  1239. //-----------------------------------------------------------------------------
  1240. // we always stock two context states, one at entry, to be able to preserve the
  1241. // state we were called with, the other one after changing to HI Graphics orientation
  1242. // (this one is used for getting back clippings etc)
  1243. //-----------------------------------------------------------------------------
  1244. // wxMacCoreGraphicsContext implementation
  1245. //-----------------------------------------------------------------------------
  1246. IMPLEMENT_DYNAMIC_CLASS(wxMacCoreGraphicsContext, wxGraphicsContext)
  1247. class wxQuartzOffsetHelper
  1248. {
  1249. public :
  1250. wxQuartzOffsetHelper( CGContextRef cg , bool offset )
  1251. {
  1252. m_cg = cg;
  1253. m_offset = offset;
  1254. if ( m_offset )
  1255. {
  1256. m_userOffset = CGContextConvertSizeToUserSpace( m_cg, CGSizeMake( 0.5 , 0.5 ) );
  1257. CGContextTranslateCTM( m_cg, m_userOffset.width , m_userOffset.height );
  1258. }
  1259. else
  1260. {
  1261. m_userOffset = CGSizeMake(0.0, 0.0);
  1262. }
  1263. }
  1264. ~wxQuartzOffsetHelper( )
  1265. {
  1266. if ( m_offset )
  1267. CGContextTranslateCTM( m_cg, -m_userOffset.width , -m_userOffset.height );
  1268. }
  1269. public :
  1270. CGSize m_userOffset;
  1271. CGContextRef m_cg;
  1272. bool m_offset;
  1273. } ;
  1274. void wxMacCoreGraphicsContext::Init()
  1275. {
  1276. m_cgContext = NULL;
  1277. m_contextSynthesized = false;
  1278. m_width = 0;
  1279. m_height = 0;
  1280. #if wxOSX_USE_CARBON
  1281. m_windowRef = NULL;
  1282. #endif
  1283. #if wxOSX_USE_COCOA_OR_IPHONE
  1284. m_view = NULL;
  1285. #endif
  1286. m_invisible = false;
  1287. m_antialias = wxANTIALIAS_DEFAULT;
  1288. m_interpolation = wxINTERPOLATION_DEFAULT;
  1289. }
  1290. wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, CGContextRef cgcontext, wxDouble width, wxDouble height ) : wxGraphicsContext(renderer)
  1291. {
  1292. Init();
  1293. SetNativeContext(cgcontext);
  1294. m_width = width;
  1295. m_height = height;
  1296. }
  1297. #if wxOSX_USE_CARBON
  1298. wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, WindowRef window ): wxGraphicsContext(renderer)
  1299. {
  1300. Init();
  1301. m_windowRef = window;
  1302. m_enableOffset = true;
  1303. }
  1304. #endif
  1305. wxMacCoreGraphicsContext::wxMacCoreGraphicsContext( wxGraphicsRenderer* renderer, wxWindow* window ): wxGraphicsContext(renderer)
  1306. {
  1307. Init();
  1308. m_enableOffset = true;
  1309. wxSize sz = window->GetSize();
  1310. m_width = sz.x;
  1311. m_height = sz.y;
  1312. #if wxOSX_USE_COCOA_OR_IPHONE
  1313. m_view = window->GetHandle();
  1314. #if wxOSX_USE_COCOA
  1315. if ( ! window->GetPeer()->IsFlipped() )
  1316. {
  1317. m_windowTransform = CGAffineTransformMakeTranslation( 0 , m_height );
  1318. m_windowTransform = CGAffineTransformScale( m_windowTransform , 1 , -1 );
  1319. }
  1320. else
  1321. #endif
  1322. {
  1323. m_windowTransform = CGAffineTransformIdentity;
  1324. }
  1325. #else
  1326. int originX , originY;
  1327. originX = originY = 0;
  1328. Rect bounds = { 0,0,0,0 };
  1329. m_windowRef = (WindowRef) window->MacGetTopLevelWindowRef();
  1330. window->MacWindowToRootWindow( &o