aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/SimpleCocoaApp/SkNSView.mm
blob: 2ce19ac6b06f3bb17e96a35d01a75af8405c307e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#import "SkView.h"
#import "SkMatrix.h"
#import "SkCanvas.h"

class SkNSContainerView : public SkView {
public:
    SkNSContainerView(NSView* parent){
        fParent = parent;
        fMatrix.reset();
    }
    void setBeforeChildMatrix(const SkMatrix& m) {fMatrix = m;}
    
protected:
    virtual bool handleInval(const SkRect*) {
        [fParent setNeedsDisplay:YES];
        return true;
    }
    virtual void beforeChild(SkView* child, SkCanvas* canvas) {
        canvas->concat(fMatrix);
    }
    virtual void onSizeChange() {
        this->INHERITED::onSizeChange();
        SkView::F2BIter iter(this);
        SkView* view = iter.next();
        while (view) {
            view->setSize(this->width(), this->height());
            view = iter.next();
        }
    }
    
private:
    NSView*  fParent;
    SkMatrix fMatrix;
    
    typedef SkView INHERITED;
};

////////////////////////////////////////////////////////////////////////////////
#import "SkCGUtils.h"
#import "SkNSView.h"
@implementation SkNSView
@synthesize offset, center, scale, rotation;

-(id) initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        fView = new SkNSContainerView(self);
        fView->setVisibleP(true);
        NSSize viewSize = [self bounds].size;
        fView->setSize(viewSize.width, viewSize.height);
        
        [self resetTransformations];
    }
    return self;
}

-(void) dealloc {
    delete fView;
    [super dealloc];
}

-(void) addSkView:(SkView*)aView {
    fView->attachChildToFront(aView);
}

-(BOOL) isFlipped {
    return YES;
}

-(BOOL) inLiveResize {
    if (fView != nil) {
        NSSize s = [self bounds].size;
        fView->setSize(s.width, s.height);
        [self setNeedsDisplay:YES];
    }
    return [super inLiveResize];
}

-(void) resetTransformations {
    offset = NSMakePoint(0, 0);
    center = NSMakePoint(fView->width() / 2.0, fView->height() / 2.0);
    rotation = 0;
    scale = 1.0;
}

-(void) drawRect:(NSRect)dirtyRect {
    //TODO -- check if our NSView is backed by a CALayer, and possibly use 
    //skia's gpu backend
    if (fView != nil) {
        SkBitmap bitmap;
        bitmap.setConfig(SkBitmap::kARGB_8888_Config, fView->width(), 
                         fView->height());
        bitmap.allocPixels();
        SkCanvas canvas(bitmap);
        
        //Apply view transformations so they can be applied to individual 
        //child views without affecting the parent's clip/matrix
        SkMatrix matrix;
        matrix.setTranslate(offset.x + center.x, offset.y + center.y);
        matrix.preRotate(rotation);
        matrix.preScale(scale, scale);
        matrix.preTranslate(-center.x, -center.y);
        fView->setBeforeChildMatrix(matrix);

        fView->draw(&canvas);
        
        //Draw bitmap
        NSImage * image = [[NSImage alloc] init];
        CGImageRef cgimage = SkCreateCGImageRef(bitmap);
        NSBitmapImageRep * bitmapRep = 
        [[NSBitmapImageRep alloc] initWithCGImage:cgimage];
        
        [image addRepresentation:bitmapRep];
        [image setSize:NSMakeSize(fView->width(), fView->height())];
        [image setFlipped:TRUE];
        [image drawAtPoint:NSMakePoint(0, 0)
                  fromRect: NSZeroRect
                 operation: NSCompositeSourceOver
                  fraction: 1.0];
        [image release]; 
        CGImageRelease(cgimage);
        [bitmapRep release];
    }
}
@end