GNU Smalltalk でお絵かき ―GNU Smalltak で cairo のお勉強 その3
結局今回なんで cairo で遊んでみようと思ったかと言うと、Squeak のお気に入りのお絵かきスクリプト
| pen | pen := Pen new roundNib: 8; color: Color red. [Sensor yellowButtonPressed not] whileTrue: [ Sensor redButtonPressed ifTrue: [pen goto: Sensor cursorPoint] ifFalse: [pen place: Sensor cursorPoint]]
みたいなことをやるのに、GNU Smalltalk GTK では どれくらいになるのかな?・・と思ってしまったからです。やりたかったのはそれだけだったのですが、なかなかスムースにいかなくて。いつものことですが...orz
#!/usr/bin/env gst PackageLoader fileInPackage: 'GTK'. PackageLoader fileInPackage: 'Cairo'. GTK.GtkWidget extend [ getPointer [ | x y | x := CInt value: 0. y := CInt value: 0. self getPointer: x y: y. ^x value @ y value ] ] Object subclass: MainWindow [ | window penDown pathList | pathList [ ^pathList ifNil:[pathList := OrderedCollection new] ] addPath: selector point: point [ "selector = #moveTo:, #lineTo: ..etc" ((self pathList notEmpty) and: [point = self pathList last argument]) ifFalse: [ self pathList add: (Message selector: selector argument: point). ^true ]. ^false ] delete: aWiget event: aGdkEvent [ GTK.Gtk mainQuit. ^false ] penDown [ ^penDown ifNil:[penDown := false] ] penDown: aWidget event: aGdkEvent [ penDown := true. 'penDown!' printNl. (self addPath: #moveTo: point: aWidget getPointer) ifTrue: [ aWidget getWindow withContextDo: [:cairoCtx| self pathList last sendTo: cairoCtx. cairoCtx stroke ] ] ] penUp: aWidget event: aGdkEvent [ penDown := false. 'penUp!' printNl. ] mouseMove: aWidget event: aGdkEvent [ self penDown ifTrue: [ (self addPath: #lineTo: point: aWidget getPointer) ifTrue: [ aWidget getWindow withContextDo: [:cairoCtx | (self pathList at: self pathList size -1) sendTo: cairoCtx. self pathList last sendTo: cairoCtx. cairoCtx stroke ] ] ] ] expose: aWidget event: aGdkEvent [ aWidget getWindow withContextDo: [:cairoCtx | cairoCtx lineCap: #round; lineWidth: 3.0. self pathList notEmpty ifTrue: [ self pathList do: [ :msg | Transcript show: 'exec:'; showCr: msg printString. msg sendTo: cairoCtx ]. cairoCtx stroke ] ]. ^false ] show [ | box canvas gdkDrawable cairoSf cairoCtx | window := GTK.GtkWindow new: GTK.Gtk gtkWindowToplevel. window setTitle: 'Cario Lean'. window connectSignal: 'delete_event' to: self selector: #delete:event: userData: nil. window setDefaultSize: 200 height: 200. canvas := GTK.GtkDrawingArea new. window add: canvas. canvas connectSignal: 'expose-event' to: self selector: #expose:event: userData: nil. canvas setEvents: (GTK.Gdk gdkButtonPressMask bitOr: (GTK.Gdk gdkButtonReleaseMask bitOr: GTK.Gdk gdkPointerMotionMask)). canvas connectSignal: 'button_press_event' to: self selector: #penDown:event: userData: nil. canvas connectSignal: 'button_release_event' to: self selector: #penUp:event: userData: nil. canvas connectSignal: 'motion_notify_event' to: self selector: #mouseMove:event: userData: nil. window showAll. ] ] Eval [ window := MainWindow new. window show. GTK.Gtk main ]
実行したところはこんな感じです。
職場だったんで、トラボでお絵かきしたのですが、、、無謀が身に染みまくりです。(絵になりませぬ...orz)*1
expose event の再描画ときにペンの太さをかえているので、window を最小化したりサイズかえたりするとこんなのになります。
ベクターグラフィックだよ、という主張のつもりでしたが、たんに滲んだだけにしか見えませぬ。失敗(T△T
まぁ、入力されたデータをそのまま極小直線にしたのでは、ドット絵とかわらないですよね。そこらへんをよろしくやるあたりとか面白そうなお題かもかも*2。それ以前に、ぶっちゃけ何も考えないで作っているので、 データ的にも動作的にもかなり重いので、そこからですね。
* * *
というわけで、GW 前の 仕事のキリの悪いことをいいわけに、ちょっとサボちゃった風味なエントリーはこれにておしまいでし。