Source

CocoaPDF / TronPDFView.mm

Full commit
//
//  TronPDFView.mm
//  cocoapdf
//
//  Created by Quincy on 10-07-25.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#import "TronPDFView.h"
#import "TronScrollView.h"

NSString * TronPDFViewPageChangedNotification = @"TronPDFViewPageChangedNotification";
NSString * TronPDFViewScrollChangedNotification = @"TronPDFViewScrollChangedNotification";

@implementation TronPDFView

#pragma mark callback functions
void beginRendering(void* data) {
}

void endRendering(void* data, bool canceled) {
    if (!canceled) {
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
        [(TronPDFView*)data setNeedsDisplay:YES];
        [pool drain];
    }
}

void currPageProc(int current_page, int num_pages, void *data) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    [(TronPDFView*)data postPageChangeNotification];
    [pool drain];
}

/**
 * copy 1 pixel from src to dst and flip y coordinate
 */
void cp_1_pixel(const char * src, char * dst, int i, int j, int width, int height) {
    int src_idx = (i * width + j) * 4;
    int dst_idx = ((height - i - 1) * width + j) * 4;
    dst[dst_idx] = src[src_idx + 2];
    dst[dst_idx + 1] = src[src_idx + 1];
    dst[dst_idx + 2] = src[src_idx];
    dst[dst_idx + 3] = src[src_idx + 3];
}

#pragma mark private helper methods

-(BOOL)doesPDFViewHaveDoc {
    return (_tronPDFView && _tronPDFView->GetDoc());
}

#pragma mark objc code 

@synthesize tronPDFView = _tronPDFView;

- (pdftron::PDF::PDFView *) getPDFView {
    return _tronPDFView;
}

- (void)awakeFromNib {
    [super awakeFromNib];
    _tronPDFView = new pdftron::PDF::PDFView();
}

#pragma mark draw view

-(BOOL)isFlipped {
    return YES;
}

- (void)drawRect:(NSRect)dirtyRect {
    if ([self doesPDFViewHaveDoc]) {
        const char* bgra = _tronPDFView->GetBuffer();
        if (bgra) {
            int width = _tronPDFView->GetBufferWidth();
            int height = _tronPDFView->GetBufferHeight();

            char * rgba = &_buf[0];
            
            for (int i = 0; i < height; ++i) {
                for (int j = 0; j < width; ++j) {
                    cp_1_pixel(bgra, rgba, i, j, width, height);
                }
            }
            
            CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
            CGContextRef bitmapContext = CGBitmapContextCreate(rgba,
                                                               width,
                                                               height,
                                                               8, // bitsPerComponent
                                                               4*width, // bytesPerRow
                                                               colorSpace,
                                                               kCGImageAlphaPremultipliedLast);
            
            CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext);
            
            __strong NSGraphicsContext * nsGraphicsContext = [NSGraphicsContext currentContext];
            __strong CGContextRef zCgContextRef = (CGContextRef) [nsGraphicsContext graphicsPort];            
            
            CGRect	zCgRect	= NSRectToCGRect([[self superview] bounds]);

            CGContextDrawImage(zCgContextRef, zCgRect, cgImage);
            
            CFRelease(colorSpace);            
            CFRelease(cgImage);
            CFRelease(bitmapContext);
        }
    }
}


- (void)dealloc {
    if (_tronPDFView) {
        _tronPDFView->~PDFView();
    }
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super dealloc];
}

- (void)setDocument:(MyPDFDoc*) myDoc {
    if (_tronPDFView) {
        _tronPDFView->SetDoc(*(myDoc.tronPDFDoc));
        _tronPDFView->SetRenderBeginProc(beginRendering, self);
        _tronPDFView->SetRenderFinishProc(endRendering, self);
        _tronPDFView->SetCurrentPageProc(currPageProc, self);
        _tronPDFView->SetPageViewMode(pdftron::PDF::PDFView::e_fit_width);
        _tronPDFView->SetPagePresentationMode(pdftron::PDF::PDFView::e_single_continuous);
        _tronPDFView->SetPageSpacing(10, 10, 20, 10);
        [self windowResized:nil];
    }
}
/*
- (void)viewDidMoveToWindow
{
    [super viewDidMoveToWindow];
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(windowResized:) 
                                                 name:NSWindowDidResizeNotification 
                                               object:[self window]];
}
  
 */


- (void)windowResized:(NSNotification *)notification;
{
    if (_tronPDFView)
    {
        NSSize size = [[self superview] bounds].size;
        int width = (int) size.width;
        int height = (int) size.height;
        _tronPDFView->OnSize(width, height);
    
        double w = _tronPDFView->GetCanvasWidth();
        double h = _tronPDFView->GetCanvasHeight();
        [self setFrameSize:NSMakeSize(w, h)];

        //allocate buffer
        _buf.resize(width * height * 4, NULL);
        
        [self setNeedsDisplay:YES];
    }
}

#pragma mark event handling
- (BOOL)acceptsFirstResponder 
{
    return YES;
}

- (void)mouseDown:(NSEvent*)theEvent {
    NSLog(@"mouseDown");
}

- (void)mouseDragged:(NSEvent*)theEvent {
    NSLog(@"mouseDragged");
}

- (void)mouseUp:(NSEvent*)theEvent {
    NSLog(@"mouseUp");
}

- (void)mouseMoved:(NSEvent*)theEvent {
    NSLog(@"mouseMoved"); 
}

- (void)mouseEntered:(NSEvent*)theEvent {
    NSLog(@"mouseEntered"); 
}

- (void)mouseExited:(NSEvent*)theEvent {
    NSLog(@"mouseExited");
}

- (void)keyDown:(NSEvent*)theEvent {
    NSLog(@"keyDown");
}

- (void)keyUp:(NSEvent*)theEvent {
    NSLog(@"keyUp");
}

- (void)setScroll:(float)hPos verticalPosition:(float)vPos {
    if ([self doesPDFViewHaveDoc]) {
        double final_hPos = hPos * _tronPDFView->GetCanvasWidth();
        double final_vPos = vPos * _tronPDFView->GetCanvasHeight();
        //[self scrollPoint:NSMakePoint(final_hPos, final_vPos)];
        _tronPDFView->SetHScrollPos(final_hPos);
        _tronPDFView->SetVScrollPos(final_vPos);
        _tronPDFView->Update();
        [self setNeedsDisplay:YES];
    }
}

#pragma mark notifications

-(void)postPageChangeNotification {
    [[NSNotificationCenter defaultCenter] postNotificationName:TronPDFViewPageChangedNotification
                                                        object:self];
}

-(void)postScrollChangeNotification {
    NSLog(@"postScrollChangeNotification");
    [[NSNotificationCenter defaultCenter] postNotificationName:TronPDFViewScrollChangedNotification
                                                        object:self];
     
}

#pragma mark PDFView Wrapper
-(int)currPageNum {
    int currPageNum = 0;
    if ([self doesPDFViewHaveDoc]) {
        currPageNum = _tronPDFView->GetCurrentPage();
    }
    return currPageNum;
}

-(double)currentHorizontalScrollPosition {
    double hPos = 0.0;
    if ([self doesPDFViewHaveDoc]) {
        hPos = _tronPDFView->GetHScrollPos() / _tronPDFView->GetCanvasWidth();
    }
    return hPos;
}

-(double)currentVerticalScrollPosition {
    double vPos = 0.0;
    if ([self doesPDFViewHaveDoc]) {
        vPos = _tronPDFView->GetVScrollPos() / _tronPDFView->GetCanvasHeight();
    }
    return vPos;
}

-(void)goToNextPage:(id)sender {
    if ([self doesPDFViewHaveDoc]) {
        _tronPDFView->GotoNextPage();
        _tronPDFView->Update();
        [self postScrollChangeNotification];
        [self setNeedsDisplay:YES];
    }
}

-(void)goToPreviousPage:(id)sender {
    if ([self doesPDFViewHaveDoc]) {
        _tronPDFView->GotoPreviousPage();
        _tronPDFView->Update();
        [self postScrollChangeNotification];
        [self setNeedsDisplay:YES];
    }
}

@end