1
1
mirror of https://github.com/exyte/Macaw.git synced 2024-09-11 13:15:35 +03:00

Disabling renderer event by individual node

This commit is contained in:
Victor Sukochev 2016-09-08 18:19:53 +06:00
parent c1773e4f24
commit b4a907c0f7
7 changed files with 79 additions and 83 deletions

View File

@ -4,14 +4,11 @@ import RxSwift
class GroupRenderer: NodeRenderer {
var animationCache: AnimationCache
let group: Group
init(group: Group, ctx: RenderContext, animationCache: AnimationCache) {
self.group = group
self.animationCache = animationCache
super.init(node: group, ctx: ctx)
super.init(node: group, ctx: ctx, animationCache: animationCache)
}
override func addObservers() {
@ -25,6 +22,8 @@ class GroupRenderer: NodeRenderer {
override func render(force: Bool, opacity: Double) {
super.render(force, opacity: opacity)
if !force {
// Cutting animated content

View File

@ -6,9 +6,9 @@ class ImageRenderer: NodeRenderer {
var renderedPaths: [CGPath] = [CGPath]()
init(image: Image, ctx: RenderContext) {
init(image: Image, ctx: RenderContext, animationCache: AnimationCache) {
self.image = image
super.init(node: image, ctx: ctx)
super.init(node: image, ctx: ctx, animationCache: animationCache)
}
override func node() -> Node {
@ -26,6 +26,8 @@ class ImageRenderer: NodeRenderer {
}
override func render(force: Bool, opacity: Double) {
super.render(force, opacity: opacity)
if let uiimage = UIImage(named: image.src) {
let imageSize = uiimage.size
var w = CGFloat(image.w)

View File

@ -8,9 +8,11 @@ class NodeRenderer {
private let onNodeChange: (Any) -> Void
private let disposables = GroupDisposable()
let animationCache: AnimationCache
init(node: Node, ctx: RenderContext) {
init(node: Node, ctx: RenderContext, animationCache: AnimationCache) {
self.ctx = ctx
self.animationCache = animationCache
onNodeChange = { (_: Any) in ctx.view?.setNeedsDisplay() }
addObservers()
}
@ -44,7 +46,11 @@ class NodeRenderer {
}
public func render(force: Bool, opacity: Double) {
if animationCache.isAnimating(node()) {
self.removeObservers()
} else {
self.addObservers()
}
}
public func detectTouches(location: CGPoint) -> [Shape] {

View File

@ -47,7 +47,7 @@ class RenderUtils {
} else if let text = node as? Text {
return TextRenderer(text: text, ctx: context, animationCache: animationCache)
} else if let image = node as? Image {
return ImageRenderer(image: image, ctx: context)
return ImageRenderer(image: image, ctx: context, animationCache: animationCache)
}
fatalError("Unsupported node: \(node)");
}

View File

@ -5,12 +5,9 @@ class ShapeRenderer: NodeRenderer {
let shape: Shape
let animationCache: AnimationCache
init(shape: Shape, ctx: RenderContext, animationCache: AnimationCache) {
self.shape = shape
self.animationCache = animationCache
super.init(node: shape, ctx: ctx)
super.init(node: shape, ctx: ctx, animationCache: animationCache)
}
override func node() -> Node {
@ -26,9 +23,11 @@ class ShapeRenderer: NodeRenderer {
override func render(force: Bool, opacity: Double) {
super.render(force, opacity: opacity)
if !force {
// Cutting animated content
if animationCache.isAnimating(shape) {
if self.animationCache.isAnimating(shape) {
return
}
}
@ -484,61 +483,61 @@ class ShapeRenderer: NodeRenderer {
let color = RenderUtils.applyOpacity(strokeColor, opacity: opacity)
CGContextSetStrokeColorWithColor(ctx, RenderUtils.mapColor(color))
}
private func gradientStroke(stroke: Stroke, ctx: CGContext?, opacity: Double) {
guard let gradient = stroke.fill as? Gradient else {
return
}
CGContextReplacePathWithStrokedPath(ctx)
drawGradient(gradient, ctx: ctx, opacity: opacity)
}
private func drawGradient(gradient: Gradient, ctx: CGContext?, opacity: Double) {
CGContextSaveGState(ctx)
var colors: [CGColor] = []
var stops: [CGFloat] = []
for stop in gradient.stops {
stops.append(CGFloat(stop.offset))
let color = RenderUtils.applyOpacity(stop.color, opacity: opacity)
colors.append(RenderUtils.mapColor(color))
}
if let gradient = gradient as? LinearGradient {
var start = CGPointMake(CGFloat(gradient.x1), CGFloat(gradient.y1))
var end = CGPointMake(CGFloat(gradient.x2), CGFloat(gradient.y2))
if gradient.userSpace {
let bounds = CGContextGetPathBoundingBox(ctx)
start = CGPointMake(start.x * bounds.width + bounds.minX, start.y * bounds.height + bounds.minY)
end = CGPointMake(end.x * bounds.width + bounds.minX, end.y * bounds.height + bounds.minY)
}
CGContextClip(ctx)
let cgGradient = CGGradientCreateWithColors(CGColorSpaceCreateDeviceRGB(), colors, stops)
CGContextDrawLinearGradient(ctx, cgGradient, start, end, [.DrawsAfterEndLocation, .DrawsBeforeStartLocation])
} else if let gradient = gradient as? RadialGradient {
var innerCenter = CGPointMake(CGFloat(gradient.fx), CGFloat(gradient.fy))
var outerCenter = CGPointMake(CGFloat(gradient.cx), CGFloat(gradient.cy))
var radius = CGFloat(gradient.r)
if gradient.userSpace {
var bounds = CGContextGetPathBoundingBox(ctx)
var scaleX: CGFloat = 1
var scaleY: CGFloat = 1
if bounds.width > bounds.height {
scaleY = bounds.height / bounds.width
} else {
scaleX = bounds.width / bounds.height
}
CGContextScaleCTM(ctx, scaleX, scaleY)
bounds = CGContextGetPathBoundingBox(ctx)
innerCenter = CGPointMake(innerCenter.x * bounds.width + bounds.minX, innerCenter.y * bounds.height + bounds.minY)
outerCenter = CGPointMake(outerCenter.x * bounds.width + bounds.minX, outerCenter.y * bounds.height + bounds.minY)
radius = min(radius * bounds.width, radius * bounds.height)
}
CGContextClip(ctx)
let cgGradient = CGGradientCreateWithColors(CGColorSpaceCreateDeviceRGB(), colors, stops)
CGContextDrawRadialGradient(ctx, cgGradient, innerCenter, 0, outerCenter, radius, [.DrawsAfterEndLocation, .DrawsBeforeStartLocation])
}
CGContextRestoreGState(ctx)
}
private func gradientStroke(stroke: Stroke, ctx: CGContext?, opacity: Double) {
guard let gradient = stroke.fill as? Gradient else {
return
}
CGContextReplacePathWithStrokedPath(ctx)
drawGradient(gradient, ctx: ctx, opacity: opacity)
}
private func drawGradient(gradient: Gradient, ctx: CGContext?, opacity: Double) {
CGContextSaveGState(ctx)
var colors: [CGColor] = []
var stops: [CGFloat] = []
for stop in gradient.stops {
stops.append(CGFloat(stop.offset))
let color = RenderUtils.applyOpacity(stop.color, opacity: opacity)
colors.append(RenderUtils.mapColor(color))
}
if let gradient = gradient as? LinearGradient {
var start = CGPointMake(CGFloat(gradient.x1), CGFloat(gradient.y1))
var end = CGPointMake(CGFloat(gradient.x2), CGFloat(gradient.y2))
if gradient.userSpace {
let bounds = CGContextGetPathBoundingBox(ctx)
start = CGPointMake(start.x * bounds.width + bounds.minX, start.y * bounds.height + bounds.minY)
end = CGPointMake(end.x * bounds.width + bounds.minX, end.y * bounds.height + bounds.minY)
}
CGContextClip(ctx)
let cgGradient = CGGradientCreateWithColors(CGColorSpaceCreateDeviceRGB(), colors, stops)
CGContextDrawLinearGradient(ctx, cgGradient, start, end, [.DrawsAfterEndLocation, .DrawsBeforeStartLocation])
} else if let gradient = gradient as? RadialGradient {
var innerCenter = CGPointMake(CGFloat(gradient.fx), CGFloat(gradient.fy))
var outerCenter = CGPointMake(CGFloat(gradient.cx), CGFloat(gradient.cy))
var radius = CGFloat(gradient.r)
if gradient.userSpace {
var bounds = CGContextGetPathBoundingBox(ctx)
var scaleX: CGFloat = 1
var scaleY: CGFloat = 1
if bounds.width > bounds.height {
scaleY = bounds.height / bounds.width
} else {
scaleX = bounds.width / bounds.height
}
CGContextScaleCTM(ctx, scaleX, scaleY)
bounds = CGContextGetPathBoundingBox(ctx)
innerCenter = CGPointMake(innerCenter.x * bounds.width + bounds.minX, innerCenter.y * bounds.height + bounds.minY)
outerCenter = CGPointMake(outerCenter.x * bounds.width + bounds.minX, outerCenter.y * bounds.height + bounds.minY)
radius = min(radius * bounds.width, radius * bounds.height)
}
CGContextClip(ctx)
let cgGradient = CGGradientCreateWithColors(CGColorSpaceCreateDeviceRGB(), colors, stops)
CGContextDrawRadialGradient(ctx, cgGradient, innerCenter, 0, outerCenter, radius, [.DrawsAfterEndLocation, .DrawsBeforeStartLocation])
}
CGContextRestoreGState(ctx)
}
}

View File

@ -4,12 +4,9 @@ import UIKit
class TextRenderer: NodeRenderer {
let text: Text
let animationCache: AnimationCache
init(text: Text, ctx: RenderContext, animationCache: AnimationCache) {
self.text = text
self.animationCache = animationCache
super.init(node: text, ctx: ctx)
super.init(node: text, ctx: ctx, animationCache: animationCache)
}
override func node() -> Node {
@ -27,6 +24,8 @@ class TextRenderer: NodeRenderer {
override func render(force: Bool, opacity: Double) {
super.render(force, opacity: opacity)
if !force {
// Cutting animated content
if animationCache.isAnimating(text) {

View File

@ -57,15 +57,6 @@ public class MacawView: UIView {
}
override public func drawRect(rect: CGRect) {
if let cache = animationCache {
if cache.containsAnimation(node) {
renderer?.removeObservers()
} else {
renderer?.addObservers()
}
}
self.context.cgContext = UIGraphicsGetCurrentContext()
CGContextSaveGState(self.context.cgContext)