     return path
   }
   
-  // MARK: Wave
+  // MARK: - Wave
+  
+  private func maskWaveFromString(mask: String) {
+    let params = cleanMaskString(mask, maskName: "Wave").componentsSeparatedByString(",")
+    if params.count == 3, let unwrappedWidth = Float(params[1]), unwrappedOffset = Float(params[2]) {
+        let up = params[0] == "up"
+        maskWave(up, waveWidth: CGFloat(unwrappedWidth), waveOffset: CGFloat(unwrappedOffset))
+    } else {
+        maskWave()
+    }
+  }
   
   private func maskWaveBezierPath(waveUp: Bool, waveWidth: CGFloat, waveOffset: CGFloat) -> UIBezierPath {
     let originY = waveUp ? bounds.maxY : bounds.minY

      case .Circle:
        maskCircle()
      case .Star:
        maskStar()
      case .Polygon:
        maskPolygon()
      case .Triangle:
        maskTriangle()
      case .Wave:
        maskWave()
      }
      return
    }
    
    // Mask Star with parameter
    // Mask Wave with parameter
  }
  
  // MARK: - Mask

    drawPath(wavePath)
  }
  
  // MARK: - Private helper
  
  private func drawPath(path: UIBezierPath) {
    let maskLayer = CAShapeLayer()
    maskLayer.frame = CGRect(origin: CGPoint.zero, size: bounds.size)
    maskLayer.path = path.CGPath
    layer.mask = maskLayer
  }
  
  private func drawBorderPath(borderPath: UIBezierPath, path: UIBezierPath) {
    // FIXME: borderWidth is always set after mask, so the following code will never be excuted.
    if layer.borderWidth == 0 {
      return
