<commit_before>//
//  SnapShotCollector.swift
//  ReformApplication
//
//  Created by <NAME> on 26.08.15.
//  Copyright © 2015 <NAME>. All rights reserved.
//

import ReformMath
import ReformGraphics
import ReformCore

struct InstructionNodeKey : Hashable {
    private let node : InstructionNode

    init(_ instructionNode : InstructionNode) {
        node = instructionNode
    }

    var hashValue : Int {
        return ObjectIdentifier(node).hashValue
    }
}

func ==(lhs: InstructionNodeKey, rhs: InstructionNodeKey) -> Bool {
    return lhs.node === rhs.node
}

final public class SnapshotCollector : RuntimeListener {

    private let maxSize : (Int, Int)
    private var currentSize : (Int, Int) = (0,0)
    private var currentScaled : (Double, Double) = (0,0)
    private(set) var snapshots = [InstructionNodeKey:NSImage]()
    private(set) var instructions = Set<InstructionNodeKey>()
    private(set) var errors = [InstructionNodeKey:RuntimeError]()
    private(set) var paths = [Path]()


    private var redraw = true

    public init(maxSize : (Int, Int)) {
        self.maxSize = maxSize
    }

    public func runtimeBeginEvaluation(runtime: Runtime, withSize size: (Int, Int)) {
        paths.removeAll()
        errors.removeAll()
        instructions.removeAll()

        if currentSize.0 != size.0 || currentSize.1 != size.1 {
            snapshots.removeAll()
            currentSize = size
            let scale = min(Double(maxSize.0)/Double(currentSize.0),
                Double(maxSize.1)/Double(currentSize.1))

            currentScaled = (
                scale * Double(size.0),
                scale * Double(size.1)
            )
        }
    }

    public func runtimeFinishEvaluation(runtime: Runtime) {
    }

    public func runtime(runtime: Runtime, didEval instruction: Evaluatable) {
        guard let instruction = instruction as? InstructionNode else {
            return
        }

        let key = InstructionNodeKey(instruction)

        guard !instruction.isEmpty else {
            return
        }

        guard !instruction.isGroup else {
            return
        }

        guard !errors.keys.contains(key) else {
            return
        }

        guard !snapshots.keys.contains(key) || redraw else {
            return
        }

        let image = imageFor(key)


        do {
            image.lockFocus()
            defer { image.unlockFocus() }
            let size = image.size
            guard let context =  NSGraphicsContext.currentContext()?.CGContext else {
                return
            }

            NSColor.whiteColor().setFill()
            NSRectFill(NSRect(origin: CGPoint(), size: size))

            CGContextScaleCTM(context, size.width / CGFloat(currentSize.0), size.height / CGFloat(currentSize.1))


            NSColor.grayColor().setFill()
            NSColor.grayColor().set()
            CGContextSetLineWidth(context, 9)
            for path in paths {
                path.draw(context)
                CGContextDrawPath(context, CGPathDrawingMode.FillStroke)
            }

            for formId in runtime.getForms() {
                guard let form = runtime.get(formId) as? Drawable else {
                    continue
                }
                let isCurrent = instruction.target == formId
                let isGuide = form.drawingMode == .Guide

                guard isCurrent || !isGuide else {
                    continue
                }

                guard let path = form.getPathFor(runtime) else {
                    continue
                }
                if isGuide {
                    NSColor.cyanColor().setFill()
                    NSColor.cyanColor().set()
                } else if isCurrent {
                    NSColor.blueColor().setFill()
                    NSColor.blueColor().set()
                } else {
                    NSColor.grayColor().setFill()
                    NSColor.grayColor().set()
                }

                path.draw(context)
                CGContextDrawPath(context, CGPathDrawingMode.FillStroke)
            }
        }
    }

    func imageFor(key: InstructionNodeKey) -> NSImage {
        guard let image = snapshots[key] else {
            let image = NSImage(size: NSSize(width: CGFloat(currentScaled.0), height: CGFloat(currentScaled.1)))
            snapshots[key] = image
            return image
        }
        return image
    }

    public func runtime(runtime: Runtime, exitScopeWithForms forms: [FormIdentifier]) {

        for formId in forms {
            guard let form = runtime.get(formId) as? Drawable else {
                continue
            }

            guard form.drawingMode == .Draw else {
                continue
            }

            guard let path = form.getPathFor(runtime) else {
                continue
            }

            paths.append(path)
        }

    }

    public func runtime(runtime: Runtime, triggeredError: RuntimeError, on: Evaluatable) {
        guard let node = on as? InstructionNode else {<commit_msg>no need to realloc nsimages when picture size changes<commit_after>//
//  SnapShotCollector.swift
//  ReformApplication
//
//  Created by <NAME> on 26.08.15.
//  Copyright © 2015 <NAME>. All rights reserved.
//

import ReformMath
import ReformGraphics
import ReformCore

struct InstructionNodeKey : Hashable {
    private let node : InstructionNode

    init(_ instructionNode : InstructionNode) {
        node = instructionNode
    }

    var hashValue : Int {
        return ObjectIdentifier(node).hashValue
    }
}

func ==(lhs: InstructionNodeKey, rhs: InstructionNodeKey) -> Bool {
    return lhs.node === rhs.node
}

final public class SnapshotCollector : RuntimeListener {

    private let maxSize : (Int, Int)
    private var currentSize : (Double, Double) = (0,0)
    private var currentScaled : (Double, Double) = (0,0)
    private(set) var snapshots = [InstructionNodeKey:NSImage]()
    private(set) var instructions = Set<InstructionNodeKey>()
    private(set) var errors = [InstructionNodeKey:RuntimeError]()
    private(set) var paths = [Path]()


    private var redraw = true

    public init(maxSize : (Int, Int)) {
        self.maxSize = maxSize
    }

    public func runtimeBeginEvaluation(runtime: Runtime, withSize size: (Int, Int)) {
        paths.removeAll()
        errors.removeAll()
        instructions.removeAll()

        currentSize = (Double(size.0), Double(size.1))

        let scale = min(Double(maxSize.0)/Double(currentSize.0),
            Double(maxSize.1)/Double(currentSize.1))

        currentScaled = (
            scale * Double(size.0),
            scale * Double(size.1)
        )

    }

    public func runtimeFinishEvaluation(runtime: Runtime) {
    }

    public func runtime(runtime: Runtime, didEval instruction: Evaluatable) {
        guard let instruction = instruction as? InstructionNode else {
            return
        }

        let key = InstructionNodeKey(instruction)

        guard !instruction.isEmpty else {
            return
        }

        guard !instruction.isGroup else {
            return
        }

        guard !errors.keys.contains(key) else {
            return
        }

        guard !snapshots.keys.contains(key) || redraw else {
            return
        }

        let image = imageFor(key)


        do {
            image.lockFocus()
            defer { image.unlockFocus() }
            let size = image.size
            guard let context =  NSGraphicsContext.currentContext()?.CGContext else {
                return
            }

            CGContextClearRect(context, CGRect(origin: CGPoint(), size: size))


            CGContextTranslateCTM(context,
                (size.width -  CGFloat(currentScaled.0)) / 2,
                (size.height - CGFloat(currentScaled.1)) / 2)
            CGContextScaleCTM(context, CGFloat(currentScaled.0 / currentSize.0), CGFloat(currentScaled.1 / currentSize.1))


            CGContextSetRGBFillColor(context, 1, 1, 1, 1)
            CGContextFillRect(context, CGRect(x: 0, y: 0, width: currentSize.0, height: currentSize.1))

            CGContextSetRGBFillColor(context, 0.5,0.5,0.5,1)
            CGContextSetRGBStrokeColor(context, 0.5,0.5,0.5,1)

            CGContextSetLineWidth(context, 9)
            for path in paths {
                path.draw(context)
                CGContextDrawPath(context, CGPathDrawingMode.FillStroke)
            }

            for formId in runtime.getForms() {
                guard let form = runtime.get(formId) as? Drawable else {
                    continue
                }
                let isCurrent = instruction.target == formId
                let isGuide = form.drawingMode == .Guide

                guard isCurrent || !isGuide else {
                    continue
                }

                guard let path = form.getPathFor(runtime) else {
                    continue
                }
                if isGuide {
                    CGContextSetRGBFillColor(context, 0, 0.9, 0.9, 1.0)
                    CGContextSetRGBStrokeColor(context, 0, 0.9, 0.9, 1.0)
                } else if isCurrent {
                    CGContextSetRGBFillColor(context, 0.1, 0.5, 0.9, 1.0)
                    CGContextSetRGBStrokeColor(context, 0.1, 0.5, 0.9, 1.0)
                } else {
                    CGContextSetRGBFillColor(context, 0.5,0.5,0.5,1)
                    CGContextSetRGBStrokeColor(context, 0.5,0.5,0.5,1)
                }

                path.draw(context)
                CGContextDrawPath(context, CGPathDrawingMode.FillStroke)
            }
        }
    }

    func imageFor(key: InstructionNodeKey) -> NSImage {
        guard let image = snapshots[key] else {
            let image = NSImage(size: NSSize(width: CGFloat(maxSize.0), height: CGFloat(maxSize.1)))
            snapshots[key] = image
            return image
        }
        return image
    }

    public func runtime(runtime: Runtime, exitScopeWithForms forms: [FormIdentifier]) {

        for formId in forms {
            guard let form = runtime.get(formId) as? Drawable else {
                continue
            }

            guard form.drawingMode == .Draw else {
                continue
            }

            guard let path = form.getPathFor(runtime) else {
                continue
            }

            paths.append(path)
        }

    }

    public func runtime(runtime: Runtime, triggeredError: RuntimeError, on: Evaluatable) {
        guard let node = on as? InstructionNode else {
{'fraction_non_alphanumeric': 0.09292833412434741, 'fraction_numerical': 0.012149976269577598, 'mean_word_length': 1.7602829447209851, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3630598', 'n_tokens_mistral': 3025, 'n_tokens_neox': 2770, 'n_words': 670}