droidlabs/motion-prime

View on GitHub
motion-prime/elements/draw/_draw_background_mixin.rb

Summary

Maintainability
D
2 days
Test Coverage
module MotionPrime
  module DrawBackgroundMixin
    def draw_background_in_context(context = nil)
      context ||= UIGraphicsGetCurrentContext()
      options = draw_options
      rect, background_color, border_width, border_color, border_sides, corner_radius, dashes_array, rounded_corners = options.slice(:rect, :background_color, :border_width, :border_color, :border_sides, :corner_radius, :dashes, :rounded_corners).values

      return unless background_color || border_width > 0

      inset = border_width > 0 ? (border_width - 1 )*0.5 : 0
      rect = CGRectInset(rect, -inset, -inset)

      if dashes_array
        dashes = Pointer.new(:float, dashes_array.count)
        dashes_array.each_with_index { |length, i| dashes[i] = length }
      end

      if corner_radius > 0 && !rounded_corners
        bezier_path = UIBezierPath.bezierPathWithRoundedRect rect, cornerRadius: corner_radius
        UIGraphicsPushContext(context)
        bezier_path.setLineDash(dashes, count: dashes_array.count, phase: 0) if dashes
        if border_width > 0
          bezier_path.lineWidth = border_width
          border_color.setStroke
          bezier_path.stroke
        end
        if background_color
          background_color.setFill
          bezier_path.fill
        end
        UIGraphicsPopContext()
      elsif corner_radius > 0
        CGContextSetLineDash(context, dashes_array.count, dashes, 0) if dashes
        CGContextSetLineWidth(context, border_width) if border_width > 0
        CGContextSetStrokeColorWithColor(context, border_color.uicolor.cgcolor) if border_color
        draw_rect_in_context(context, rect: rect, radius: corner_radius, rounded_corners: rounded_corners)
        CGContextSaveGState(context)
        CGContextClip(context)
        if background_color
          CGContextSetFillColorWithColor(context, background_color.uicolor.cgcolor)
          CGContextFillRect(context, rect)
        end
        CGContextRestoreGState(context)
      else
        if border_width > 0 && border_color
          CGContextSetLineDash(context, dashes_array.count, dashes, 0) if dashes
          CGContextSetLineWidth(context, border_width)
          CGContextSetStrokeColorWithColor(context, border_color.uicolor.cgcolor)

          if border_sides.present?
            points = [
              [rect.origin.x, rect.origin.y],
              [rect.origin.x + rect.size.width, rect.origin.y],
              [rect.origin.x + rect.size.width, rect.origin.y + rect.size.height],
              [rect.origin.x, rect.origin.y + rect.size.height]
            ]
            CGContextMoveToPoint(context, *points[0])
            if border_sides.include?(:top)
              CGContextAddLineToPoint(context, *points[1])
            else
              CGContextMoveToPoint(context, *points[1])
            end
            if border_sides.include?(:right)
              CGContextAddLineToPoint(context, *points[2])
            else
              CGContextMoveToPoint(context, *points[2])
            end
            if border_sides.include?(:bottom)
              CGContextAddLineToPoint(context, *points[3])
            else
              CGContextMoveToPoint(context, *points[3])
            end
            if border_sides.include?(:left)
              CGContextAddLineToPoint(context, *points[0])
            else
              CGContextMoveToPoint(context, *points[0])
            end
            CGContextStrokePath(context)
          else
            CGContextStrokeRect(context, rect)
          end
        end

        if background_color
          CGContextSetFillColorWithColor(context, background_color.uicolor.cgcolor)
          CGContextFillRect(context, rect)
        end
      end
    end

    def draw_rect_in_context(context, options)
      rect = options.fetch(:rect)
      radius = options.fetch(:radius, 0)
      rounded_corners = options[:rounded_corners] || [:top_left, :top_right, :bottom_right, :bottom_left]

      CGContextBeginPath(context)

      x_left = rect.origin.x
      x_left_center = x_left + radius
      x_right_center = x_left + rect.size.width - radius
      x_right = x_left + rect.size.width
      y_top = rect.origin.y
      y_top_center = y_top + radius
      y_bottom_center = y_top + rect.size.height - radius
      y_bottom = y_top + rect.size.height
      CGContextMoveToPoint(context, x_left, y_top_center)

      if rounded_corners.include?(:top_left)
        CGContextAddArcToPoint(context, x_left, y_top, x_left_center, y_top, radius)
      else
        CGContextAddLineToPoint(context, x_left, y_top)
      end
      CGContextAddLineToPoint(context, x_right_center, y_top)

      if rounded_corners.include?(:top_right)
        CGContextAddArcToPoint(context, x_right, y_top, x_right, y_top_center, radius)
      else
        CGContextAddLineToPoint(context, x_right, y_top)
      end
      CGContextAddLineToPoint(context, x_right, y_bottom_center)

      if rounded_corners.include?(:bottom_right)
        CGContextAddArcToPoint(context, x_right, y_bottom, x_right_center, y_bottom, radius)
      else
        CGContextAddLineToPoint(context, x_right, y_bottom)
      end
      CGContextAddLineToPoint(context, x_left_center, y_bottom)

      if rounded_corners.include?(:bottom_left)
        CGContextAddArcToPoint(context, x_left, y_bottom, x_left, y_bottom_center, radius)
      else
        CGContextAddLineToPoint(context, x_left, y_bottom)
      end
      CGContextAddLineToPoint(context, x_left, y_top_center)

      CGContextClosePath(context)
    end
  end
end