You are here

function _canvasactions_roundedcorners_pixel_opacity in ImageCache Actions 7

Same name and namespace in other branches
  1. 8 canvasactions/rounded_corners.inc \_canvasactions_roundedcorners_pixel_opacity()
  2. 6.2 canvasactions/rounded_corners.inc \_canvasactions_roundedcorners_pixel_opacity()
  3. 6 canvasactions.inc \_canvasactions_roundedcorners_pixel_opacity()

Calculate the transparency value for a rounded corner pixel

Parameters

$x: distance from pixel center to image border (left or right) should be an integer + 0.5

$y: distance from pixel center to image border (top or bottom) should be an integer + 0.5

$r: radius of the rounded corner should be an integer

Return value

float opacity value between 0 (fully transparent) and 1 (fully opaque).

OPTIMIZE HERE! This is a really tight loop, potentially getting called thousands of times

1 call to _canvasactions_roundedcorners_pixel_opacity()
image_gd_roundedcorners in canvasactions/rounded_corners.inc
Trim rounded corners off an image, using an anti-aliasing algorithm.

File

canvasactions/rounded_corners.inc, line 223
Routines for rounded corners

Code

function _canvasactions_roundedcorners_pixel_opacity($x, $y, $r) {
  if ($x < 0 || $y < 0) {
    return 0;
  }
  else {
    if ($x > $r || $y > $r) {
      return 1;
    }
  }
  $dist_2 = ($r - $x) * ($r - $x) + ($r - $y) * ($r - $y);
  $r_2 = $r * $r;
  if ($dist_2 > ($r + 0.8) * ($r + 0.8)) {
    return 0;
  }
  else {
    if ($dist_2 < ($r - 0.8) * ($r - 0.8)) {
      return 1;
    }
    else {

      // this pixel needs special analysis.
      // thanks to a quite efficient algorithm, we can afford 10x antialiasing :)
      $opacity = 0.5;
      if ($x > $y) {

        // cut the pixel into 10 vertical "stripes"
        for ($dx = -0.45; $dx < 0.5; $dx += 0.1) {

          // find out where the rounded corner edge intersects with the stripe
          // this is plain triangle geometry.
          $dy = $r - $y - sqrt($r_2 - ($r - $x - $dx) * ($r - $x - $dx));
          $dy = $dy > 0.5 ? 0.5 : ($dy < -0.5 ? -0.5 : $dy);

          // count the opaque part of the stripe.
          $opacity -= 0.1 * $dy;
        }
      }
      else {

        // cut the pixel into 10 horizontal "stripes"
        for ($dy = -0.45; $dy < 0.5; $dy += 0.1) {

          // this is the math:
          //   ($r-$x-$dx)^2 + ($r-$y-$dy)^2 = $r^2
          //   $dx = $r - $x - sqrt($r^2 - ($r-$y-$dy)^2)
          $dx = $r - $x - sqrt($r_2 - ($r - $y - $dy) * ($r - $y - $dy));
          $dx = $dx > 0.5 ? 0.5 : ($dx < -0.5 ? -0.5 : $dx);
          $opacity -= 0.1 * $dx;
        }
      }
      return $opacity < 0 ? 0 : ($opacity > 1 ? 1 : $opacity);
    }
  }
}