28namespace Util = MacOSX::Util;
32const CGSize shadowOffset = CGSizeMake(10., 10.);
33const CGFloat shadowBlur = 5.;
40template<
class SRC,
class DST>
41struct GradientFactory {
42 static CGGradientRef CreateGradient(CGColorSpaceRef colorSpace,
43 const TColorGradient *extendedColor)
45 assert(colorSpace !=
nullptr &&
46 "GradientFactory::CreateGradient, parameter 'colorSpace' is null");
47 assert(extendedColor !=
nullptr &&
48 "GradientFactory::CreateGradient, parameter 'extendedColor' is null");
49 const SRC *compStart = extendedColor->
GetColors();
51 const std::vector<DST> convertedComponents(compStart, compEnd);
54 const std::vector<DST> convertedPositions(posStart, posEnd);
56 return CGGradientCreateWithColorComponents(colorSpace,
57 &convertedComponents[0],
58 &convertedPositions[0],
64struct GradientFactory<DST, DST> {
65 static CGGradientRef CreateGradient(CGColorSpaceRef colorSpace,
66 const TColorGradient *extendedColor)
68 assert(colorSpace !=
nullptr &&
69 "GradientFactory::CreateGradient, parameter 'colorSpace' is null");
70 assert(extendedColor !=
nullptr &&
71 "GradientFactory::CreateGradient, parameter 'extendedColor' is null");
72 const DST *comps = extendedColor->
GetColors();
74 return CGGradientCreateWithColorComponents(colorSpace, comps, pos,
79struct GradientParameters {
95 : fStartPoint(), fEndPoint(), fStartRadius(0.), fEndRadius(0.)
99 GradientParameters(
const CGPoint &
start,
const CGPoint &end)
100 : fStartPoint(
start), fEndPoint(end), fStartRadius(0.), fEndRadius(0.)
105 GradientParameters(
const CGPoint &
start,
const CGPoint &end,
106 CGFloat startRadius, CGFloat endRadius)
107 : fStartPoint(
start), fEndPoint(end), fStartRadius(startRadius), fEndRadius(endRadius)
114CGRect FindBoundingBox(
Int_t nPoints,
const TPoint *xy)
118 assert(nPoints > 2 &&
"FindBoundingBox, invalid number of points in a polygon");
119 assert(xy !=
nullptr &&
"FindBoundingBox, parameter 'xy' is null");
121 CGPoint bottomLeft = {};
122 bottomLeft.x = xy[0].
fX;
123 bottomLeft.y = xy[0].
fY;
125 CGPoint topRight = bottomLeft;
127 for (
Int_t i = 1; i < nPoints; ++i) {
128 bottomLeft.x = std::min(bottomLeft.x, CGFloat(xy[i].fX));
129 bottomLeft.y = std::min(bottomLeft.y, CGFloat(xy[i].fY));
131 topRight.x = std::max(topRight.x, CGFloat(xy[i].fX));
132 topRight.y = std::max(topRight.y, CGFloat(xy[i].fY));
135 return CGRectMake(bottomLeft.x, bottomLeft.y,
136 topRight.x - bottomLeft.x,
137 topRight.y - bottomLeft.y);
141template<
class GradientType>
142bool CalculateGradientStartEnd(
const GradientType *grad,
143 const CGSize &sizeOfDrawable,
144 Int_t n,
const TPoint *polygon,
145 GradientParameters ¶ms)
147 assert(grad !=
nullptr &&
148 "CalculateGradientStartEnd, parameter 'grad' is null");
149 assert(sizeOfDrawable.width > 0. && sizeOfDrawable.height > 0. &&
150 "CalculateGradientStartEnd, invalid destination drawable size");
152 "CalculateGradientStartEnd, parameter 'n' is not a valid number of points");
153 assert(polygon !=
nullptr &&
154 "CalculateGradientStartEnd, parameter 'polygon' is null");
158 CGPoint
start = CGPointMake(grad->GetStart().fX, grad->GetStart().fY);
159 CGPoint end = CGPointMake(grad->GetEnd().fX, grad->GetEnd().fY);
175 start.x *= sizeOfDrawable.width;
176 start.y *= sizeOfDrawable.height;
177 end.x *= sizeOfDrawable.width;
178 end.y *= sizeOfDrawable.height;
181 params.fStartPoint =
start;
182 params.fEndPoint = end;
188bool CalculateGradientRadiuses(
const TRadialGradient *grad,
189 const CGSize &sizeOfDrawable,
190 Int_t n,
const TPoint *polygon,
191 GradientParameters ¶ms)
193 assert(grad !=
nullptr &&
"CalculateGradientRadiuses, parameter 'grad' is null");
194 assert(sizeOfDrawable.width > 0. && sizeOfDrawable.height > 0. &&
195 "CalculateGradientRadiuses, invalid destination drawable size");
197 "CalculateGradientRadiuses, extended radial gradient expected");
198 assert(
n > 2 &&
"CalculateGradientRadiuses, parameter 'n' is not a valid number of points");
199 assert(polygon !=
nullptr &&
200 "CalculateGradientRadiuses, parameter 'polygon' is null");
207 CGFloat startRadius = grad->
GetR1();
208 CGFloat endRadius = grad->
GetR2();
213 startRadius *= scale;
216 const CGFloat scale = std::max(sizeOfDrawable.width, sizeOfDrawable.height);
218 startRadius *= scale;
222 params.fStartRadius = startRadius;
223 params.fEndRadius = endRadius;
229bool CalculateSimpleRadialGradientParameters(
const TRadialGradient *grad,
230 const CGSize &sizeOfDrawable,
231 Int_t n,
const TPoint *polygon,
232 GradientParameters ¶ms)
234 assert(grad !=
nullptr &&
235 "CalculateSimpleRadialGradientParameters, parameter 'grad' is null");
237 "CalculateSimpleRadialGradientParameters, invalid gradient type");
238 assert(sizeOfDrawable.width > 0. && sizeOfDrawable.height > 0. &&
239 "CCalculateSimpleRadialGradientParameters, invalid destination drawable size");
241 "CalculateSimpleRadialGradientParameters, parameter 'n' is not a valid number of points");
242 assert(polygon !=
nullptr &&
243 "CalculateSimpleRadialGradientParameters, parameter 'polygon' is null");
259 radius *= std::max(sizeOfDrawable.width, sizeOfDrawable.height);
260 center.x *= sizeOfDrawable.width;
261 center.y *= sizeOfDrawable.height;
264 params.fStartPoint = center;
265 params.fStartRadius = radius;
271bool CalculateGradientParameters(
const TColorGradient *extendedColor,
272 const CGSize &sizeOfDrawable,
273 Int_t n,
const TPoint *polygon,
274 GradientParameters ¶ms)
276 assert(extendedColor !=
nullptr &&
277 "CalculateGradientParameters, parameter 'extendedColor' is null");
278 assert(sizeOfDrawable.width > 0. && sizeOfDrawable.height > 0. &&
279 "CalculateGradientParameters, invalid destination drawable size");
280 assert(
n > 2 &&
"CalculateGradientParameters, parameter 'n' is not a valid number of points");
281 assert(polygon !=
nullptr &&
282 "CalculateGradientParameters, parameter 'polygon' is null");
284 if (
const TLinearGradient *
const gl =
dynamic_cast<const TLinearGradient *
>(extendedColor))
285 return CalculateGradientStartEnd(gl, sizeOfDrawable,
n, polygon, params);
286 else if (
const TRadialGradient *
const gr =
dynamic_cast<const TRadialGradient *
>(extendedColor)) {
288 return CalculateSimpleRadialGradientParameters(
gr, sizeOfDrawable,
n, polygon, params);
290 if (CalculateGradientStartEnd(
gr, sizeOfDrawable,
n, polygon, params))
291 return CalculateGradientRadiuses(
gr, sizeOfDrawable,
n, polygon, params);
296 assert(0 &&
"CalculateGradientParamters, unknown gradient type");
306 assert(ctx !=
nullptr &&
"SetFillColor, ctx parameter is null");
317 const CGFloat alpha = color->GetAlpha();
320 color->GetRGB(rgb[0], rgb[1], rgb[2]);
321 CGContextSetRGBFillColor(ctx, rgb[0], rgb[1], rgb[2], alpha);
329 assert(data !=
nullptr &&
"DrawPattern, data parameter is null");
330 assert(ctx !=
nullptr &&
"DrawPattern, ctx parameter is null");
333 const unsigned stencilIndex = *
static_cast<unsigned *
>(data);
335 for (
int i = 30,
y = 0; i >= 0; i -= 2, ++
y) {
337 for (
int j = 0; j < 8; ++j, ++
x) {
338 if (
gStipples[stencilIndex][i] & (1 << j))
339 CGContextFillRect(ctx, CGRectMake(
x,
y, 1, 1));
342 for (
int j = 0; j < 8; ++j, ++
x) {
343 if (
gStipples[stencilIndex][i + 1] & (1 << j))
344 CGContextFillRect(ctx, CGRectMake(
x,
y, 1, 1));
352 assert(ctx !=
nullptr &&
"SetFillPattern, ctx parameter is null");
353 assert(patternIndex !=
nullptr &&
"SetFillPattern, patternIndex parameter is null");
355 const TColor *fillColor =
gROOT->GetColor(attrFillColor);
366 if (!baseSpace.
Get())
370 if (!patternSpace.
Get())
373 CGContextSetFillColorSpace(ctx, patternSpace.
Get());
375 CGPatternCallbacks callbacks = {0, &
DrawPattern, 0};
377 CGRectMake(0, 0, 16, 16),
378 CGAffineTransformIdentity, 16, 16,
379 kCGPatternTilingConstantSpacing,
385 CGContextSetFillPattern(ctx, pattern.
Get(), rgba);
393 assert(ctx !=
nullptr &&
"SetFillAreaParameters, ctx parameter is null");
398 const unsigned fillStyle = attFillStyle / 1000;
401 if (fillStyle == 2 || (fillStyle != 1 && fillStyle != 3)) {
403 ::Error(
"SetFillAreaParameters",
"Line color for index %d was not found",
int(attFillColor));
406 }
else if (fillStyle == 1) {
409 ::Error(
"SetFillAreaParameters",
"Fill color for index %d was not found",
int(attFillColor));
413 assert(patternIndex !=
nullptr &&
"SetFillAreaParameters, pattern index in null");
415 *patternIndex = attFillStyle % 1000;
417 if (*patternIndex > 25)
421 ::Error(
"SetFillAreaParameters",
"SetFillPattern failed");
440 CGContextStrokeRect(ctx, CGRectMake(x1, y1, x2 - x1, y2 - y1));
442 CGContextFillRect(ctx, CGRectMake(x1, y1, x2 - x1, y2 - y1));
452 assert(ctx !=
nullptr &&
"DrawFillArea, ctx parameter is null");
453 assert(xy !=
nullptr &&
"DrawFillArea, xy parameter is null");
455 CGContextBeginPath(ctx);
457 CGContextMoveToPoint(ctx, xy[0].fX, xy[0].fY);
458 for (
Int_t i = 1; i <
n; ++i)
459 CGContextAddLineToPoint(ctx, xy[i].fX, xy[i].fY);
461 CGContextClosePath(ctx);
463 const unsigned fillStyle = attfill.
GetFillStyle() / 1000;
466 if (fillStyle == 2 || (fillStyle != 1 && fillStyle != 3)) {
467 CGContextStrokePath(ctx);
468 }
else if (fillStyle == 1) {
470 CGContextSetShadow(ctx, shadowOffset, shadowBlur);
472 CGContextFillPath(ctx);
475 CGContextSetShadow(ctx, shadowOffset, shadowBlur);
477 CGContextFillPath(ctx);
487 assert(ctx !=
nullptr &&
"DrawPolygonWithGradientFill, ctx parameter is null");
488 assert(nPoints != 0 &&
"DrawPolygonWithGradientFill, nPoints parameter is 0");
489 assert(xy !=
nullptr &&
"DrawPolygonWithGradientFill, xy parameter is null");
490 assert(extendedColor !=
nullptr &&
491 "DrawPolygonWithGradientFill, extendedColor parameter is null");
493 if (!sizeOfDrawable.width || !sizeOfDrawable.height)
496 const CFScopeGuard<CGMutablePathRef> path(CGPathCreateMutable());
498 ::Error(
"DrawPolygonWithGradientFill",
"CGPathCreateMutable failed");
503 const CFScopeGuard<CGColorSpaceRef> baseSpace(CGColorSpaceCreateDeviceRGB());
504 if (!baseSpace.Get()) {
505 ::Error(
"DrawPolygonWithGradientFill",
"CGColorSpaceCreateDeviceRGB failed");
509 typedef GradientFactory<Double_t, CGFloat>
Factory;
510 const CFScopeGuard<CGGradientRef> gradient(Factory::CreateGradient(baseSpace.Get(), extendedColor));
511 if (!gradient.Get()) {
512 ::Error(
"DrawPolygonWithGradientFill",
"CGGradientCreateWithColorComponents failed");
517 CGPathMoveToPoint(path.Get(),
nullptr, xy[0].
fX, xy[0].
fY);
518 for (
Int_t i = 1; i < nPoints; ++i)
519 CGPathAddLineToPoint(path.Get(),
nullptr, xy[i].
fX, xy[i].
fY);
521 CGPathCloseSubpath(path.Get());
528 CGContextSetRGBFillColor(ctx, 1., 1., 1., 0.5);
529 CGContextBeginPath(ctx);
530 CGContextAddPath(ctx, path.Get());
531 CGContextSetShadow(ctx, shadowOffset, shadowBlur);
532 CGContextFillPath(ctx);
535 CGContextBeginPath(ctx);
536 CGContextAddPath(ctx, path.Get());
539 GradientParameters params;
540 if (!CalculateGradientParameters(extendedColor, sizeOfDrawable, nPoints, xy, params))
544 if (
gr && (params.fStartRadius || params.fEndRadius)) {
546 CGContextDrawRadialGradient(ctx, gradient.Get(), params.fStartPoint, 0.,
547 params.fStartPoint, params.fStartRadius,
548 kCGGradientDrawsAfterEndLocation |
549 kCGGradientDrawsBeforeStartLocation);
551 CGContextDrawRadialGradient(ctx, gradient.Get(), params.fStartPoint, params.fStartRadius,
552 params.fEndPoint, params.fEndRadius,
553 kCGGradientDrawsAfterEndLocation |
554 kCGGradientDrawsBeforeStartLocation);
557 CGContextDrawLinearGradient(ctx, gradient.Get(),
558 params.fStartPoint, params.fEndPoint,
559 kCGGradientDrawsAfterEndLocation |
560 kCGGradientDrawsBeforeStartLocation);
const unsigned char gStipples[26][32]
int Int_t
Signed integer 4 bytes (int).
bool Bool_t
Boolean (0=false, 1=true) (bool).
short Color_t
Color number (short).
short Style_t
Style number (short).
float Float_t
Float 4 bytes (float).
Error("WriteTObject","The current directory (%s) is not associated with a file. The object (%s) has not been written.", GetName(), objname)
virtual Color_t GetFillColor() const
Return the fill area color.
virtual Style_t GetFillStyle() const
Return the fill area style.
TColorGradient extends basic TColor.
const Double_t * GetColors() const
Get colors.
SizeType_t GetNumberOfSteps() const
Get number of steps.
ECoordinateMode GetCoordinateMode() const
Get coordinate mode.
const Double_t * GetColorPositions() const
Get color positions.
Double_t GetRadius() const
Get radius.
Double_t GetR2() const
Get R2.
const Point & GetCenter() const
Get center.
EGradientType GetGradientType() const
Get gradient type.
void DrawBox(CGContextRef ctx, Int_t x1, Int_t y1, Int_t x2, Int_t y2, bool hollow)
Bool_t SetLineColor(CGContextRef ctx, Color_t colorIndex)
void DrawPattern(void *data, CGContextRef ctx)
Bool_t SetFillAreaParameters(CGContextRef ctx, unsigned *patternIndex, const TAttFill &attfill)
void DrawFillArea(CGContextRef ctx, Int_t n, TPoint *xy, Bool_t drawShadow, const TAttFill &attfill)
Bool_t SetFillColor(CGContextRef ctx, Color_t colorIndex)
void DrawPolygonWithGradientFill(CGContextRef ctx, const TColorGradient *extendedColor, const CGSize &sizeOfDrawable, Int_t nPoints, const TPoint *xy, Bool_t drawShadow)
bool SetFillPattern(CGContextRef ctx, const unsigned *patternIndex, Color_t attrFillColor)