macOS 版 comipoli も PDF 対応にしたい。
NSPDFImageRep – AppKit | Apple Developer Documentation
こんなものがあったのか!
しかも NSImage からの継承。
ということは NSImage のメソッドもそのまま使えるってことだ。
elif is_pdf and re.search(r'\.pdf$', path, re.I): self.status = 3 self.namelist.clear() data = NSData.dataWithContentsOfFile_(path) self.pdf = NSPDFImageRep.alloc().initWithData_(data) ###### elif self.status == 3: self.pdf.setCurrentPage_(num) return self.pdf
を前々回のソースに追記するだけで本当にイケた!
ただ cairo と Poppler の時と同じように背景は白で塗りつぶす必要があった。
しかし、画像だけの PDF だとトンデモなく表示が重いんですけど。。。。。
テキストだけの PDF なら余裕なんだけど。
筆者の mac は最新機とはいえ Air だし、pro なら。。。。。
もしかして Core Graphics を直で使ったら軽くなるかな?
と思ったので試すことに。
PyObjC の CoreGraphics は以下に入っていた
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/Quartz
PDF Document Creation, Viewing, and Transforming
上記を PyObjC で簡単に使ってみる。
PATH は自前で持っている PDF に書き換えてください。
#!/usr/bin/env python3 import objc from AppKit import * from Quartz.CoreGraphics import * #PATH = '/Users/sasakima-nao/Documents/ProgrammingWithObjectiveC.pdf' PATH = '/Users/sasakima-nao/Documents/big_picture.pdf' class ComipoliView(NSView): def init(self): objc.super(ComipoliView, self).init() # PDF Document url = NSURL.fileURLWithPath_isDirectory_(PATH, False) self.pdfdoc = CGPDFDocumentCreateWithURL(url) self.max_page = CGPDFDocumentGetNumberOfPages(self.pdfdoc) self.page_number = 1 return self def drawRect_(self, rect): NSColor.blackColor().set() NSRectFill(rect) # CGContext ctx = NSGraphicsContext.currentContext().CGContext() page = CGPDFDocumentGetPage(self.pdfdoc, self.page_number) # # Draw (x1) #CGContextDrawPDFPage(ctx, page) # # Resize Draw CGContextSaveGState(ctx) # start m = CGPDFPageGetDrawingTransform(page, kCGPDFMediaBox, rect, 0, True) CGContextConcatCTM(ctx, m) # background color is white cgrect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox) NSColor.whiteColor().set() CGContextFillRect(ctx, cgrect) # clip CGContextClipToRect(ctx, cgrect) CGContextDrawPDFPage(ctx, page) # end CGContextRestoreGState(ctx) class ComipoliWindow(NSWindow): def init(self): frame = NSMakeRect(100, 400, 900, 600) objc.super(ComipoliWindow, self).initWithContentRect_styleMask_backing_defer_( frame, NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask, NSBackingStoreBuffered, False) self.setTitle_('draw PDF') self.setDelegate_(self) # view self.canvas = ComipoliView.new() self.canvas.setFrameSize_(frame.size) self.contentView().addSubview_(self.canvas) return self def nextPage(self): if self.canvas.max_page > self.canvas.page_number: self.canvas.page_number += 1 self.canvas.display() if self.canvas.max_page == self.canvas.page_number: self.setTitle_('end') def windowDidResize_(self, sender): aw = self.contentView().frame().size.width ah = self.contentView().frame().size.height size = NSMakeSize(aw, ah) self.canvas.setFrameSize_(size) class ComipoliMenu(NSMenu): def init(self): objc.super(ComipoliMenu, self).init() item_app = NSMenuItem.new() self.addItem_(item_app) menu_app = NSMenu.new() item_app.setSubmenu_(menu_app) item_next = NSMenuItem.new() item_next.initWithTitle_action_keyEquivalent_('NextPage', 'nextPage:', 'n') item_next.setTarget_(self) menu_app.addItem_(item_next) item_quit = NSMenuItem.new() item_quit.initWithTitle_action_keyEquivalent_('Quit', 'terminate:', 'q') menu_app.addItem_(item_quit) return self def nextPage_(self, sender): NSApp.keyWindow().nextPage() NSApplication.sharedApplication() window = ComipoliWindow.new() window.makeKeyAndOrderFront_(window) NSApp.setMainMenu_(ComipoliMenu.new()) NSApp.activateIgnoringOtherApps_(True) NSApp.run()
command+N で次ページ
って、ほとんど変わらないヤン!
結局この作業を NSPDFImageRep は内部でやっているだけなんだろう。
軽くしたきゃ cbz に変換してくれで済ませよう。
そんなことより。
PyObjC ってこんなことまでできるのかい!
書いた筆者が驚いた、Xcode マジでいらね。