|
10 | 10 |
|
11 | 11 | static const CGFloat RCTViewBorderThreshold = 0.001; |
12 | 12 |
|
| 13 | +CGFloat RCTMaxBorderInset(UIEdgeInsets borderInsets) |
| 14 | +{ |
| 15 | + return MAX(MAX(borderInsets.top, borderInsets.left), MAX(borderInsets.bottom, borderInsets.right)); |
| 16 | +} |
| 17 | + |
13 | 18 | BOOL RCTBorderInsetsAreEqual(UIEdgeInsets borderInsets) |
14 | 19 | { |
15 | 20 | return ABS(borderInsets.left - borderInsets.right) < RCTViewBorderThreshold && |
@@ -415,8 +420,8 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn |
415 | 420 | return image; |
416 | 421 | } |
417 | 422 |
|
418 | | -// Currently, the dashed / dotted implementation only supports a single colour + |
419 | | -// single width, as that's currently required and supported on Android. |
| 423 | +// Currently, the dashed / dotted implementation only supports a single colour, |
| 424 | +// as that's currently required and supported on Android. |
420 | 425 | // |
421 | 426 | // Supporting individual widths + colours on each side is possible by modifying |
422 | 427 | // the current implementation. The idea is that we will draw four different lines |
@@ -486,12 +491,12 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn |
486 | 491 | { |
487 | 492 | NSCParameterAssert(borderStyle == RCTBorderStyleDashed || borderStyle == RCTBorderStyleDotted); |
488 | 493 |
|
489 | | - if (!RCTBorderColorsAreEqual(borderColors) || !RCTBorderInsetsAreEqual(borderInsets)) { |
| 494 | + if (!RCTBorderColorsAreEqual(borderColors)) { |
490 | 495 | RCTLogWarn(@"Unsupported dashed / dotted border style"); |
491 | 496 | return nil; |
492 | 497 | } |
493 | 498 |
|
494 | | - const CGFloat lineWidth = borderInsets.top; |
| 499 | + const CGFloat lineWidth = RCTMaxBorderInset(borderInsets); |
495 | 500 | if (lineWidth <= 0.0) { |
496 | 501 | return nil; |
497 | 502 | } |
@@ -519,6 +524,34 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn |
519 | 524 | CGPathRef path = |
520 | 525 | RCTPathCreateWithRoundedRect(pathRect, RCTGetCornerInsets(cornerRadii, UIEdgeInsetsZero), NULL, NO); |
521 | 526 |
|
| 527 | + if (!RCTBorderInsetsAreEqual(borderInsets)) { |
| 528 | + CGContextSaveGState(context); |
| 529 | + { |
| 530 | + // Create a path representing the full rect |
| 531 | + CGMutablePathRef outerPath = CGPathCreateMutable(); |
| 532 | + CGPathAddRect(outerPath, NULL, rect); |
| 533 | + |
| 534 | + CGRect insetRect = CGRectMake( |
| 535 | + rect.origin.x + borderInsets.left, |
| 536 | + rect.origin.y + borderInsets.top, |
| 537 | + rect.size.width - borderInsets.left - borderInsets.right, |
| 538 | + rect.size.height - borderInsets.top - borderInsets.bottom); |
| 539 | + |
| 540 | + // The padding edge (inner border) radius is the outer border radius minus the corresponding border thickness |
| 541 | + CGPathRef innerRoundedRect = |
| 542 | + RCTPathCreateWithRoundedRect(insetRect, RCTGetCornerInsets(cornerRadii, borderInsets), NULL, NO); |
| 543 | + |
| 544 | + // Add both paths to outerPath |
| 545 | + CGPathAddPath(outerPath, NULL, innerRoundedRect); |
| 546 | + |
| 547 | + // Clip using even-odd |
| 548 | + CGContextAddPath(context, outerPath); |
| 549 | + CGContextEOClip(context); |
| 550 | + CGPathRelease(outerPath); |
| 551 | + CGPathRelease(innerRoundedRect); |
| 552 | + } |
| 553 | + } |
| 554 | + |
522 | 555 | CGFloat dashLengths[2]; |
523 | 556 | dashLengths[0] = dashLengths[1] = (borderStyle == RCTBorderStyleDashed ? 3 : 1) * lineWidth; |
524 | 557 |
|
|
0 commit comments