root/as3/gunyarapaint/trunk/gunyarapaint/src/org/libspark/gunyarapaint/entities/GPLogger.as

リビジョン 1654, 41.0 kB (コミッタ: tasuku, コミット時期: 5 年 前)

rgb infomation show on draw window

Line 
1 // 今考えると、このクラス全体的に設計がおかしい。
2 // 定数持っているなら、それを外部から指定してもらうべきだし、
3 // 読み込みのswitchは同じような処理を2回やって無駄だ。
4
5 package org.libspark.gunyarapaint.entities
6 {
7   import flash.display.BitmapData;
8   import flash.errors.EOFError;
9   import flash.events.MouseEvent;
10   import flash.geom.Point;
11   import flash.utils.ByteArray;
12  
13   import mx.controls.Alert;
14   import mx.core.Application;
15   import mx.utils.Base64Decoder;
16   import mx.utils.Base64Encoder;
17  
18   import org.libspark.gunyarapaint.controls.GPCanvas;
19   import org.libspark.gunyarapaint.controls.GPCanvasWindowControl;
20   import org.libspark.gunyarapaint.controls.GPLayerWindowControl;
21   import org.libspark.gunyarapaint.controls.PenDetailWindowControl;
22  
23   public class GPLogger
24   {
25     [Embed(source="../../../../../imgs/icon_dropper.png")] private var dropperIcon:Class;
26     [Embed(source="../../../../../imgs/icon_hand_open.png")] private var handOpenIcon:Class;
27     [Embed(source="../../../../../imgs/icon_hand_close.png")] private var handCloseIcon:Class;
28
29     // 座標差分計算用
30     private var preX:uint, preY:uint;
31     private var preAction:String = '';
32    
33     private var _logCount:uint; // ログのイベント数
34     private var _log:ByteArray; // 圧縮されていない状態を保持
35     private var _canvasWidth:uint, _canvasHeight:uint; // キャンバスサイズ
36     private var _undoBufferSize:uint; // アンドゥバッファサイズ
37     private var _startLogPosition:uint; // ログのヘッダを読み終えた後の位置
38     private var _baseLayers:BitmapData; // 基となる絵
39     private var _baseInfo:Object; // 基となる絵のメタ情報
40    
41     private var _changeUndoRedoHandler:Function;
42
43     // 各種エンティティたち
44     private var _canvas:GPCanvas; // 大本のGPCanvas
45
46     // 互換性。つか、過去のバグやマズった設計で作られたログについてちゃんと再生できるようにする。
47     public var compatibility_0_0_1:Boolean = false;
48
49     public function GPLogger(log:ByteArray,
50                              onLogging:Boolean,
51                              canvasWidth:uint,
52                              canvasHeight:uint,
53                              undoBufferSize:uint,
54                              baseLayers:BitmapData,
55                              baseInfo:Object
56                             ):void {
57
58       // ログは、ヘッダ部分を飛ばしたところにカーソルが当たっていることを前提としている
59       // あと、BIG_ENDIANね。
60       _log = log;
61       _onLogging = onLogging;
62       _canvasWidth = canvasWidth;
63       _canvasHeight = canvasHeight;
64       _undoBufferSize = undoBufferSize;
65       _baseLayers = baseLayers;
66       _baseInfo = baseInfo;
67      
68       var app:Object = Application.application;
69       try {
70         _canvasWindow = app.gpCanvasWindow;
71         _penWindow = app.penDetailWindow;
72         _layerWindow = app.gpLayerWindow;
73         _changeUndoRedoHandler = app.changeUndoRedoHandler;
74       } catch (e:ReferenceError) {
75         _canvasWindow = null;
76         _penWindow = null;
77         _layerWindow = null;
78         _changeUndoRedoHandler = function (u:uint, r:uint):void {};
79       }
80       _startLogPosition = _log.position;
81     }
82
83     // グローバルイベントハンドラ・変数としてのloggerをみんなに配る
84     public function createCanvas():void {
85       _layerArray = GPLayerArray.createFromLayersImageInfo(this, _baseLayers, _baseInfo);
86       if (_onLogging) {
87         _canvas = new GPCanvas(this);
88       }
89       _pen = new GPPen(this);
90       _undoBuffer = new GPUndoBuffer(this);
91       if (_canvasWindow) {
92         _canvasWindow.logger = this;
93       }
94       if (_penWindow) {
95         _penWindow.logger = this;
96       }
97       if (_layerWindow) {
98         _layerWindow.logger = this;
99       }
100     }
101
102     // 再生用・ふっかつのじゅもん用
103     public static function createFromByteArray(log:ByteArray,
104                                                onLogging:Boolean,
105                                                baseLayers:BitmapData,
106                                                baseInfo:Object
107                                               ):GPLogger {
108       log.endian = flash.utils.Endian.BIG_ENDIAN;
109       var buf:String = log.readUTFBytes(14);
110       if (buf != 'GUNYARA_PAINT:') {
111         Alert('不正なお絵カキコのログです。');
112         return null;
113       }
114       buf = log.readUTFBytes(6);
115       var width:uint = log.readShort();
116       var height:uint = log.readShort();
117       var undoBufferSize:uint = log.readShort();
118
119       var ret:GPLogger = new GPLogger(log, onLogging, width, height, undoBufferSize, baseLayers, baseInfo);
120       switch (buf) {
121       case '0.0.1:':
122         ret.compatibility_0_0_1 = true;
123         break;
124       case '0.0.2:': // 0.5ずれバグの修正、ドット描画バグの修正
125       case '0.0.3:': // レイヤ対応初版、最初の数点は0.0.2versionでレイヤのやつがある
126       case '0.0.4:':
127       case '0.0.5:':
128       case '0.0.6:':
129       case '0.0.7:':
130       case '0.0.8:': // undo時のために、GPLayerでの描画時にbitmapDataをcloneするように、
131                        // & レイヤの可視・不可視をundoバッファに積まないようにする。
132       case '0.0.9:': // ドット絵ペン追加、lineTo/ドット絵で無駄なログが出ないように
133       case '0.1.0:': // レイヤー統合のUndoでbitmapDataをcloneしていなかった問題を修正
134                        // mergeWithBelowの実装を変えて、統合後のalpha値を1に設定するようにした。
135         break;
136       default:
137         Alert('このバージョンのログには対応しておりません。ブラウザをリロードしてみてください。');
138         return null;
139       }
140       ret.createCanvas();
141       return ret;
142     }
143    
144     // 描画用
145     public static function createForDraw(width:uint, height:uint,
146                                          undoBufferSize:uint,
147                                          baseLayers:BitmapData,
148                                          baseInfo:Object
149                                         ):GPLogger {
150       var log:ByteArray = new ByteArray();
151       log.endian = flash.utils.Endian.BIG_ENDIAN;
152       log.writeUTFBytes('GUNYARA_PAINT:0.1.0:');
153       log.writeShort(width);
154       log.writeShort(height);
155       log.writeShort(undoBufferSize);
156       var ret:GPLogger = new GPLogger(log, true, width, height, undoBufferSize, baseLayers, baseInfo);
157       ret.createCanvas();
158
159       return ret;
160     }
161
162
163     // ACTIONは6bit長 0x3fまで
164     public static const ACTION_NONE:uint = 0;
165     public static const ACTION_MOVETO:uint = 1;
166     public static const ACTION_LINETO:uint = 2;
167     public static const ACTION_LINESTYLE:uint = 3;
168     public static const ACTION_DRAW_SHAPE_ON_BITMAP:uint = 4;
169     public static const ACTION_UNDO:uint = 5;
170     public static const ACTION_REDO:uint = 6;
171     public static const ACTION_BEGIN_FILL:uint = 7;
172     public static const ACTION_END_FILL:uint = 8;
173     public static const ACTION_DRAW_RECT:uint = 9;
174     public static const ACTION_DRAW_CIRCLE:uint = 10;
175     public static const ACTION_DRAW_ELLIPSE:uint = 11;
176     public static const ACTION_DRAW_ROUND_RECT:uint = 12;
177     public static const ACTION_FLOOD_FILL:uint = 13;
178     public static const ACTION_LAYER_NEW:uint = 14;
179     public static const ACTION_LAYER_COPY:uint = 15;
180     public static const ACTION_LAYER_SWAP:uint = 16;
181     public static const ACTION_LAYER_MERGE_WITH_BELOW:uint = 17;
182     public static const ACTION_LAYER_REMOVE:uint = 18;
183     public static const ACTION_LAYER_CHANGE_TARGET:uint = 19;
184     public static const ACTION_LAYER_CHANGE_VISIBLE:uint = 20;
185     public static const ACTION_LAYER_CHANGE_BLEND_MODE:uint = 21;
186     public static const ACTION_LAYER_CHANGE_ALPHA:uint = 22;
187     public static const ACTION_SET_PIXEL:uint = 23;
188
189     // LINESTYLE
190     public static const LINESTYLE_THICKNESS:uint = 1;
191     public static const LINESTYLE_COLOR:uint = 2;
192     public static const LINESTYLE_ALPHA:uint = 3;
193     public static const LINESTYLE_BLEND_MODE:uint = 4;
194     public static const LINESTYLE_SCALE_MODE:uint = 5;
195     public static const LINESTYLE_CAPS:uint = 6;
196     public static const LINESTYLE_JOINTS:uint = 7;
197     public static const LINESTYLE_MITER_LIMIT:uint = 8;
198     public static const LINESTYLE_PIXEL_HINTING:uint = 9; // NB: not used! first version, this is true
199
200     private var _pen:GPPen;
201     private var _layerArray:GPLayerArray;
202     private var _undoBuffer:GPUndoBuffer;
203
204     private function pushUndoBuffer():void {
205       _undoBuffer.push(_layerArray);
206       _changeUndoRedoHandler(_undoBuffer.undoCount, _undoBuffer.redoCount);
207     }
208
209     public function drawShapeOnBitmap():void {
210       _layerArray.draw(_pen.drawShape, null, null, _pen.blendMode, null, false);
211       pushUndoBuffer();
212       invokeRemoveDrawLayer();
213     }
214    
215     private function invokeInsertDrawLayer():void {
216       _pen.setLineStyle();
217       _layerArray.insertDrawLayer(_pen.drawShape, _pen);     
218     }
219    
220     private function invokeRemoveDrawLayer():void {
221       _layerArray.removeDrawLayer(_pen.drawShape);
222       _pen.clearDrawShape();
223     }
224
225     /** log write **/
226
227     private function writeByte(byte:int):void {
228       _log.writeByte(byte);
229     }
230     private function writeShort(value:int):void {
231       _log.writeShort(value);
232     }
233     private function writeUInt(value:uint):void {
234       _log.writeUnsignedInt(value);
235     }
236     private function writeDouble(value:Number):void {
237       _log.writeDouble(value);
238     }
239     private function writeUTF(value:String):void {
240       _log.writeUTF(value);
241     }
242     private function writeBoolean(value:Boolean):void {
243       _log.writeByte(value ? 1 : 0);
244     }
245     private function readByte():uint {
246       return _log.readUnsignedByte();
247     }
248     private function readShort():int {
249       return _log.readShort();
250     }
251     private function readUShort():uint {
252       return uint(_log.readShort() & 0xffff);
253     }
254     private function readUInt():uint {
255       return _log.readUnsignedInt();
256     }
257     private function readDouble():Number {
258       return _log.readDouble();
259     }
260     private function readUTF():String {
261       return _log.readUTF();
262     }
263     private function readBoolean():Boolean {
264       return (_log.readByte() == 1);
265     }
266
267     // ログ関係のローカル変数
268     private var _playLogIntervalId:uint;
269     private var _playSpeed:uint;
270
271     public function set playSpeed(speed:uint):void {
272       _playSpeed = speed;
273     }
274    
275     private var _playCompleteCallback:Function;
276
277     public function play(speed:uint, callback:Function):void {
278       _playSpeed = speed;
279       _playCompleteCallback = callback;
280       _playLogIntervalId = flash.utils.setInterval(playNext, 50);
281     }
282
283     private var _preAction:uint = ACTION_NONE; // for avoid version 0.0.1 bug...◆
284     private function playNext():void {
285       for (var i:uint = 0; i < _playSpeed; i++) {
286         if (!read()) {
287           flash.utils.clearInterval(_playLogIntervalId);
288           _playCompleteCallback();
289           break;
290         }
291         if (_layerArray.view.numChildren != _layerArray.length) {
292           // check logic
293         }
294       }
295     }
296    
297     public function read():Boolean {
298       var byte:uint;
299       var dx:int, dy:int;
300       var short:uint;
301
302       var uintNum:uint;
303       var uintNum2:uint;
304       var str:String;
305       var doubleNum:Number;
306       var bool:Boolean;
307      
308       try {
309         byte = readByte();
310
311 /*
312         if (compatibility_0_0_1 &&
313             _preAction == GPLogger.ACTION_MOVETO && action != GPLogger.ACTION_LINETO) {
314           _pen.drawOldBugPointRect();
315         }
316 */
317
318         switch (byte) {
319         case ACTION_MOVETO:
320           dx = readShort();
321           dy = readShort();
322           preX += dx;
323           preY += dy;
324           eventMoveTo(preX, preY);
325           break;
326         case ACTION_LINETO:
327           dx = readShort();
328           dy = readShort();
329           preX += dx;
330           preY += dy;
331           eventLineTo(preX, preY);
332           break;
333         case ACTION_LINESTYLE:
334           dx = readByte(); // style type
335           switch (dx) {
336           case GPLogger.LINESTYLE_THICKNESS:
337             uintNum = readByte();
338             eventLineStyleThickness(uintNum);
339             break;
340           case GPLogger.LINESTYLE_COLOR:
341             uintNum = readUInt();
342             eventLineStyleColor(uintNum);
343             break;
344           case GPLogger.LINESTYLE_ALPHA:
345             doubleNum = readDouble();
346             eventLineStyleAlpha(doubleNum);
347             break;
348           case GPLogger.LINESTYLE_MITER_LIMIT:
349             doubleNum = readDouble();
350             eventLineStyleMiterLimit(doubleNum);
351             break;
352           case GPLogger.LINESTYLE_BLEND_MODE:
353             str = readUTF();
354             eventLineStyleBlendMode(str);
355             break;
356           case GPLogger.LINESTYLE_SCALE_MODE:
357             str = readUTF();
358             eventLineStyleScaleMode(str);
359             break;
360           case GPLogger.LINESTYLE_CAPS:
361             str = readUTF();
362             eventLineStyleCapsStyle(str);
363             break;
364           case GPLogger.LINESTYLE_JOINTS:
365             str = readUTF();
366             eventLineStyleJointStyle(str);
367             break;
368           case GPLogger.LINESTYLE_PIXEL_HINTING:
369             bool = readBoolean();
370             eventLineStylePixelHinting(bool);
371             break;
372           default:
373             Alert.show('未対応のラインスタイルです。');
374             break;
375           }
376           break;
377         case ACTION_DRAW_SHAPE_ON_BITMAP:
378           eventDrawShapeOnBitmap();
379           break;
380         case ACTION_UNDO:
381           eventUndo();
382           break;
383         case ACTION_REDO:
384           eventRedo();
385           break;
386         case ACTION_BEGIN_FILL:
387           uintNum = readUInt();
388           doubleNum = readDouble();
389           eventBeginFill(uintNum, doubleNum);
390           break;
391         case ACTION_END_FILL:
392           eventEndFill();
393           break;
394         case ACTION_DRAW_CIRCLE:
395           doubleNum = readDouble();
396           eventDrawCircle(doubleNum);
397           break;
398         case ACTION_FLOOD_FILL:
399           eventFloodFill();
400           break;
401         case ACTION_LAYER_NEW:
402           eventLayerNew();
403           break;
404         case ACTION_LAYER_COPY:
405           eventLayerCopy();
406           break;
407         case ACTION_LAYER_SWAP:
408           uintNum = readByte();
409           uintNum2 = readByte();
410           eventLayerSwap(uintNum, uintNum2);
411           break;
412         case ACTION_LAYER_MERGE_WITH_BELOW:
413           eventLayerMergeWithBelow();
414           break;
415         case ACTION_LAYER_REMOVE:
416           eventLayerRemove();
417           break;
418         case ACTION_LAYER_CHANGE_TARGET:
419           uintNum = readByte();
420           eventLayerChangeTarget(uintNum);
421           break;
422         case ACTION_LAYER_CHANGE_VISIBLE:
423           uintNum = readByte();
424           bool = readBoolean();
425           eventLayerChangeVisible(uintNum, bool);
426           break;
427         case ACTION_LAYER_CHANGE_BLEND_MODE:
428           str = readUTF();
429           eventLayerChangeBlendMode(str);
430           break;
431         case ACTION_LAYER_CHANGE_ALPHA:
432           doubleNum = readDouble();
433           eventLayerChangeAlpha(doubleNum);
434           break;
435         case ACTION_SET_PIXEL:
436           uintNum = readShort();
437           uintNum2 = readShort();
438           eventSetPixel(uintNum, uintNum2);
439           break;
440         default:
441           if (byte & 0x80) {
442             if (byte & 0x40) {
443               // 7bit lineTo
444               _log.position -= 1;
445               short = readShort();
446               dx = (short << 18) >> 25;
447               dy = (short << 25) >> 25;
448             } else {
449               // 3bit lineTo
450               dx = (byte << 26) >> 29;
451               dy = (byte << 29) >> 29;
452             }
453             preX += dx;
454             preY += dy;
455             eventLineTo(preX, preY);
456           } else if (byte & 0x40) {
457             // 7bit moveTo
458             _log.position -= 1;
459             short = readShort();
460             dx = (short << 18) >> 25;
461             dy = (short << 25) >> 25;
462             preX += dx;
463             preY += dy;
464             eventMoveTo(preX, preY);
465           } else {
466             Alert.show('未対応のアクションです。');
467             // error
468           }
469         }
470         _preAction = byte;
471         return true;
472       } catch (e:EOFError) {
473       }
474       return false;
475     }
476
477     public function resetInstance():void {
478       _log.position = _startLogPosition;
479       preX = 0; preY = 0; _logCount = 0;
480     }
481
482     public function get password():String {
483       var pos:uint = _log.position;
484       var e:Base64Encoder = new Base64Encoder();
485       _log.compress();
486       e.encodeBytes(_log);
487       _log.uncompress();
488       _log.position = pos;
489       return e.flush();
490     }
491    
492     public static function deserialize(s:String,
493                                        changeImageCallback:Function,
494                                        undoRedoCallback:Function,
495                                        baseLayers:BitmapData,
496                                        baseInfo:Object
497                                       ):GPLogger {
498       var e:Base64Decoder = new Base64Decoder();
499       e.decode(s);
500       var b:ByteArray = e.toByteArray();
501       b.uncompress();
502       return createFromByteArray(b, true, baseLayers, baseInfo);
503     }
504
505     /**********************************************/
506     /* 新メソッド */
507     private var _preX:int, _preY:int; // ログで差分エンコードするときに必要な直線のmoveTo/lineToの値
508     private var _onLogging:Boolean = false; // ログ取得中かどうか
509    
510     private var _drawApplication:Application;
511     private var _canvasWindow:GPCanvasWindowControl;
512     private var _penWindow:PenDetailWindowControl;
513     private var _layerWindow:GPLayerWindowControl;
514
515     public function eventMoveTo(x:Number, y:Number):void {
516       var ix:int = Math.floor(x);
517       var iy:int = Math.floor(y);
518       var dx:int = ix - _preX;
519       var dy:int = iy - _preY;
520       if (_onLogging) {
521         if (dx >= -64 && dx <= 63 && dy >= -64 && dy <= 63) {
522           // dxもdyも7bitに収まる場合
523           writeShort(0x4000 | (dx << 7) & 0x3f80 | dy & 0x7f);
524         } else {
525           writeByte(ACTION_MOVETO);
526           writeShort(dx);
527           writeShort(dy);
528         }
529         _preX = ix;
530         _preY = iy;
531         _logCount++;
532       }
533       _pen.moveTo(ix, iy);
534       trace('MOVE_TO x:' + ix + ' y:' + iy);
535      
536       invokeInsertDrawLayer();
537       _drawedLine = false;
538     }
539    
540     public function eventLineTo(x:Number, y:Number):void {
541       var ix:int = Math.floor(x);
542       var iy:int = Math.floor(y);
543       if (!_pen.lineTo(ix, iy)) { // 同じ座標だったらイベントキャンセル
544         return;
545       }
546       if (_onLogging) {
547         var dx:int = ix - _preX;
548         var dy:int = iy - _preY;
549         if (dx >= -64 && dx <= 63 && dy >= -64 && dy <= 63) {
550           // dxもdyも7bitに収まる場合
551           writeShort(0xc000 | (dx << 7) & 0x3f80 | dy & 0x7f);
552         } else {
553           writeByte(ACTION_LINETO);
554           writeShort(dx);
555           writeShort(dy);
556         }
557         _preX = ix;
558         _preY = iy;
559         _logCount++;
560       }
561       trace('LINE_TO x:' + ix + ' y:' + iy);
562       _drawedLine = true;
563     }
564    
565     private function invokePenChange():void {
566       if (_penWindow) {
567         _penWindow.changePen(_pen.mode, _pen.color, _pen.alpha, _pen.thickness);
568       }
569     }
570    
571     private function invokePenCancelTool():void {
572       if (_penWindow) {
573         _penWindow.cancelTool();
574       }
575     }
576
577     // 一時的にUIのみのペン状態を変える
578     private function invokePenTempChange(mode:uint, color:uint, alpha:Number, thickness:uint):void {
579       if (_penWindow) {
580         _penWindow.changePen(mode, color, alpha, thickness);
581       }     
582     }
583    
584     public function eventLineStyleThickness(thickness:uint):void {
585       if (_pen.thickness == thickness) {
586         return;
587       }
588       if (_onLogging) {
589         writeByte(ACTION_LINESTYLE);
590         writeByte(LINESTYLE_THICKNESS);
591         writeByte(thickness);
592         _logCount++;
593       }
594       _pen.thickness = thickness;
595       trace('LINE_STYLE thickness:' + thickness);
596
597       invokePenChange();
598     }
599    
600     public function eventLineStyleColor(rgbcolor:uint):void {
601       if (_pen.color == rgbcolor) {
602         return;
603       }
604       if (_onLogging) {
605         writeByte(ACTION_LINESTYLE);
606         writeByte(LINESTYLE_COLOR);
607         writeUInt(rgbcolor);
608         _logCount++;
609       }
610       _pen.color = rgbcolor;
611       trace('LINE_STYLE color:' + rgbcolor);
612
613       invokePenChange();
614     }
615    
616     public function eventLineStyleAlpha(alpha:Number):void {
617       if (_pen.alpha == alpha) {
618         return;
619       }
620       if (_onLogging) {
621         writeByte(ACTION_LINESTYLE);
622         writeByte(LINESTYLE_ALPHA);
623         writeDouble(alpha);
624         _logCount++;
625       }
626       _pen.alpha = alpha;
627       trace('LINE_STYLE alpha:' + alpha);
628
629       invokePenChange();
630     }
631    
632     public function eventLineStyleMiterLimit(miterLimit:Number):void {
633       if (_pen.miterLimit == miterLimit) {
634         return;
635       }
636       if (_onLogging) {
637         writeByte(ACTION_LINESTYLE);
638         writeByte(LINESTYLE_MITER_LIMIT);
639         writeDouble(miterLimit);
640         _logCount++;
641       }
642       _pen.miterLimit = miterLimit;
643       trace('LINE_STYLE miterLimit:' + miterLimit);
644
645       invokePenChange();
646     }
647    
648     public function eventLineStyleBlendMode(blendMode:String):void {
649       if (_pen.blendMode == blendMode) {
650         return;
651       }
652       if (_onLogging) {
653         writeByte(ACTION_LINESTYLE);
654         writeByte(LINESTYLE_BLEND_MODE);
655         writeUTF(blendMode);
656         _logCount++;
657       }
658       _pen.blendMode = blendMode;
659       trace('LINE_STYLE blendMode:' + blendMode);
660
661       invokePenChange();
662     }
663    
664     public function eventLineStyleScaleMode(scaleMode:String):void {
665       if (_pen.scaleMode == scaleMode) {
666         return;
667       }
668       if (_onLogging) {
669         writeByte(ACTION_LINESTYLE);
670         writeByte(LINESTYLE_SCALE_MODE);
671         writeUTF(scaleMode);
672         _logCount++;
673       }
674       _pen.scaleMode = scaleMode;
675       trace('LINE_STYLE scaleMode:' + scaleMode);
676
677       invokePenChange();
678     }
679    
680     public function eventLineStyleCapsStyle(capsStyle:String):void {
681       if (_pen.capsStyle == capsStyle) {
682         return;
683       }
684       if (_onLogging) {
685         writeByte(ACTION_LINESTYLE);
686         writeByte(LINESTYLE_CAPS);
687         writeUTF(capsStyle);
688         _logCount++;
689       }
690       _pen.capsStyle = capsStyle;
691       trace('LINE_STYLE capsStyle:' + capsStyle);
692
693       invokePenChange();
694     }
695    
696     public function eventLineStyleJointStyle(jointStyle:String):void {
697       if (_pen.jointStyle == jointStyle) {
698         return;
699       }
700       if (_onLogging) {
701         writeByte(ACTION_LINESTYLE);
702         writeByte(LINESTYLE_JOINTS);
703         writeUTF(jointStyle);
704         _logCount++;
705       }
706       _pen.jointStyle = jointStyle;
707       trace('LINE_STYLE jointStyle:' + jointStyle);
708
709       invokePenChange();
710     }
711    
712     public function eventLineStylePixelHinting(pixelHinting:Boolean):void {
713       if (_pen.pixelHinting == pixelHinting) {
714         return;
715       }
716       if (_onLogging) {
717         writeByte(ACTION_LINESTYLE);
718         writeByte(LINESTYLE_PIXEL_HINTING);
719         writeBoolean(pixelHinting);
720         _logCount++;
721       }
722       _pen.pixelHinting = pixelHinting;
723       trace('LINE_STYLE pixelHinting:' + pixelHinting);
724
725       invokePenChange();
726     }
727    
728     public function eventDrawShapeOnBitmap():void {
729       if (_onLogging) {
730         writeByte(ACTION_DRAW_SHAPE_ON_BITMAP);
731         _logCount++;
732       }
733       this.drawShapeOnBitmap();
734       trace('DRAW_SHAPE_ON_BITMAP');
735     }
736    
737     public function eventUndo():void {
738       var obj:Object = _undoBuffer.undo();
739       if (!obj) {
740         return;
741       }
742       if (_onLogging) {
743         writeByte(ACTION_UNDO);
744         _logCount++;
745       }
746       _layerArray.dataForUndo = obj;
747       _changeUndoRedoHandler(_undoBuffer.undoCount, _undoBuffer.redoCount);
748       invokeLayerChange();
749       trace('UNDO');
750     }
751    
752     public function eventRedo():void {
753       var obj:Object = _undoBuffer.redo();
754       if (!obj) {
755         return;
756       }
757       if (_onLogging) {
758         writeByte(ACTION_REDO);
759         _logCount++;
760       }
761       _layerArray.dataForUndo = obj;
762       _changeUndoRedoHandler(_undoBuffer.undoCount, _undoBuffer.redoCount);
763       invokeLayerChange();
764       trace('REDO');
765     }
766    
767     public function eventBeginFill(color:uint, alpha:Number):void {
768       if (_onLogging) {
769         writeByte(ACTION_BEGIN_FILL);
770         writeUInt(color);
771         writeDouble(alpha);
772         _logCount++;
773       }
774       _pen.beginFill(color, alpha);
775       trace('BEGIN_FILL color:'+ color + ' alpha:' + alpha);
776     }
777    
778     public function eventEndFill():void {
779       if (_onLogging) {
780         writeByte(ACTION_END_FILL);
781         _logCount++;
782       }
783       _pen.endFill();
784       trace('END_FILL');
785     }
786    
787     public function eventDrawCircle(radius:Number):void {
788       if (_onLogging) {
789         // 直前のmoveToの座標を中心。よって、半径のみ保存
790         writeByte(ACTION_DRAW_CIRCLE);
791         writeDouble(radius);
792         _logCount++;
793       }
794       _pen.drawCircle(radius);
795       trace('DRAW_CIRCLE radius:' + radius);
796     }
797    
798     public function eventFloodFill():void {
799       if (_onLogging) {
800         writeByte(ACTION_FLOOD_FILL);
801         _logCount++;
802       }
803       _pen.floodFill();
804       pushUndoBuffer();
805       invokeRemoveDrawLayer();
806       trace('FLOOD_FILL');
807     }
808    
809     public function eventSetPixel(x:Number, y:Number):void {
810       var ix:int = Math.floor(x);
811       var iy:int = Math.floor(y);
812       if (!_pen.setPixel(ix, iy)) { // 同じドットだったらイベントキャンセル
813         return;
814       }
815       if (_onLogging) {
816         writeByte(ACTION_SET_PIXEL);
817         writeShort(ix);
818         writeShort(iy);
819         _logCount++;
820       }
821       pushUndoBuffer();
822       trace('SET_PIXEL');
823     }
824
825     private function invokeLayerChange():void {
826       if (_layerWindow) {
827         _layerWindow.changeLayer();
828         _logCount++;
829       }
830       // _pen.setLineStyle();
831     }
832    
833     public function eventLayerNew():void {
834       if (!_layerArray.insertNew()) {
835         return;
836       }
837       if (_onLogging) {
838         writeByte(ACTION_LAYER_NEW);
839         _logCount++;
840       }
841       trace('LAYER_NEW');
842
843       pushUndoBuffer();
844       invokeLayerChange();
845     }
846    
847     public function eventLayerCopy():void {
848       if (!_layerArray.copy()) {
849         return;
850       }
851       if (_onLogging) {
852         writeByte(ACTION_LAYER_COPY);
853         _logCount++;
854       }
855       trace('LAYER_COPY');
856      
857       pushUndoBuffer();
858       invokeLayerChange();
859     }
860    
861     public function eventLayerSwap(fromIndex:uint, toIndex:uint):void {
862       if (!_layerArray.swap(fromIndex, toIndex)) {
863         return;
864       }
865       if (_onLogging) {
866         writeByte(ACTION_LAYER_SWAP);
867         writeByte(fromIndex);
868         writeByte(toIndex);
869         _logCount++;
870       }
871       trace('LAYER_SWAP from:' + fromIndex + ' to:' + toIndex);
872      
873       pushUndoBuffer();
874       invokeLayerChange();
875     }
876    
877     public function eventLayerMergeWithBelow():void {
878       if (!_layerArray.mergeWithBelow()) {
879         return;
880       }
881       if (_onLogging) {
882         writeByte(ACTION_LAYER_MERGE_WITH_BELOW);
883         _logCount++;
884       }
885       trace('LAYER_MERGE_WITH_BELOW');
886
887       pushUndoBuffer();
888       invokeLayerChange();
889     }
890    
891     public function eventLayerRemove():void {
892       if (!_layerArray.remove()) {
893         return;
894       }
895       if (_onLogging) {
896         writeByte(ACTION_LAYER_REMOVE);
897         _logCount++;
898       }
899       trace('LAYER_REMOVE');
900
901       pushUndoBuffer();
902       invokeLayerChange();
903     }
904    
905     public function eventLayerChangeTarget(target:uint):void {
906       if (_layerArray.targetIndex == target) {
907         return;
908       }
909       if (_onLogging) {
910         writeByte(ACTION_LAYER_CHANGE_TARGET);
911         writeByte(target);
912         _logCount++;
913       }
914       _layerArray.targetIndex = target;
915       trace('LAYER_CHANGE_TARGET target:' + target);
916
917       // UndoRedoには反映しない
918       invokeLayerChange();
919     }
920    
921     public function eventLayerChangeVisible(target:uint, visible:Boolean):void {
922       if (!_layerArray.changeVisible(target, visible)) {
923         return;
924       }
925       if (_onLogging) {
926         writeByte(ACTION_LAYER_CHANGE_VISIBLE);
927         writeByte(target);
928         writeBoolean(visible);
929         _logCount++;
930       }
931       trace('LAYER_CHANGE_VISIBLE target:' + target + ' value:' + visible);
932
933       // UndoRedoには反映しない from 0.9, 0.? ~ 0.8では反映していた。
934       invokeLayerChange();
935     }
936    
937     public function eventLayerChangeBlendMode(blendMode:String):void {
938       if (_layerArray.targetLayerBlendMode == blendMode) {
939         return;
940       }
941       if (_onLogging) {
942         writeByte(ACTION_LAYER_CHANGE_BLEND_MODE);
943         writeUTF(blendMode);
944         _logCount++;
945       }
946       _layerArray.targetLayerBlendMode = blendMode;
947       trace('LAYER_CHANGE_BLEND_MODE blendMode:' + blendMode);
948
949       pushUndoBuffer();
950       invokeLayerChange();
951     }
952    
953     public function eventLayerChangeAlpha(alpha:Number):void {
954       if (_layerArray.targetLayerAlpha == alpha) {
955         return;
956       }
957       if (_onLogging) {
958         writeByte(ACTION_LAYER_CHANGE_ALPHA);
959         writeDouble(alpha);
960         _logCount++;
961       }
962       _layerArray.targetLayerAlpha = alpha;
963       trace('LAYER_CHANGE_ALPHA alpha:' + alpha);
964
965       pushUndoBuffer();
966       invokeLayerChange();
967     }
968    
969     // いまはログとってないイベントたち。
970
971     public function eventLayerChangeLock(target:uint, lock:Boolean):void {
972       if (!_layerArray.changeLock(target, lock)) {
973         return;
974       }
975       if (_onLogging) {
976         //
977       }
978       // trace('LAYER_CHANGE_LOCK target:' + target + ' value:' + lock);
979     }
980    
981     public function eventCanvasMove(x:Number, y:Number):void {
982       if (_onLogging) {
983         // logging
984       }
985       _canvas.move(x, y);
986       //trace('eventCanvasMove x:' + alpha);
987     }
988    
989     public function eventCanvasScale(scale:Number):void {
990       if (_onLogging) {
991         // logging
992       }
993       _canvas.scaleX = scale;
994       _canvas.scaleY = scale;
995       //trace('eventCanvasMove scale:' + alpha);
996     }
997
998     public function eventSetAdditionalNumber(num:uint):void {
999       if (_onLogging) {
1000         // logging
1001       }
1002       _canvas.setAdditionalNumber(num);
1003     }
1004    
1005     public function eventSetAdditionalBox(visible:Boolean):void {
1006       if (_onLogging) {
1007         // logging
1008       }
1009       _canvas.setAdditionalBox(visible);
1010     }
1011
1012     public function eventSetAdditionalSkew(visible:Boolean):void {
1013       if (_onLogging) {
1014         // logging
1015       }
1016       _canvas.setAdditionalSkew(visible);
1017     }
1018    
1019     public function eventSetPenMode(mode:uint):void {
1020       if (_onLogging) {
1021         // logging
1022       }
1023       _pen.mode = mode;
1024
1025       invokePenChange();
1026
1027       if (_canvas) {
1028         switch (mode) {
1029         case GPPen.PEN_MODE_DROPPER:
1030           _canvas.setCursor(dropperIcon);
1031           break;
1032         case GPPen.PEN_MODE_HANDTOOL:
1033           _canvas.setCursor(handOpenIcon);
1034           break;
1035         case GPPen.PEN_MODE_ERASER:
1036            // FIXME: give me eraser icon
1037           _canvas.setCursor(null);
1038           break;
1039         case GPPen.PEN_MODE_PIXEL:
1040           break;
1041         default:
1042           _canvas.setCursor(null);
1043         }
1044         if (mode == GPPen.PEN_MODE_DROPPER) {
1045         } else {
1046         }       
1047       }
1048     }
1049
1050     public function get dataForPost():Object {
1051       var o:Object = _layerArray.dataForPost;
1052       o['compressed_log'] = compressedLog;
1053       o['info']['log_count'] = _logCount;
1054       o['info']['undo_buffer_size'] = _undoBufferSize;
1055       if (_penWindow) {
1056         o['info']['pen_details'] = _penWindow.dataForPost;
1057       }
1058       return o;
1059     }
1060    
1061     public function get compressedLog():ByteArray {
1062       var cl:ByteArray = new ByteArray();
1063       var tempPos:uint = _log.position;
1064       _log.compress();
1065       cl.writeBytes(_log);
1066       _log.uncompress();
1067       _log.position = tempPos;
1068       return cl;
1069     }
1070    
1071     public function get canvasWidth():uint {
1072       return _canvasWidth;
1073     }
1074
1075     public function get canvasHeight():uint {
1076       return _canvasHeight;
1077     }
1078    
1079     public function get undoBufferSize():uint {
1080       return _undoBufferSize;
1081     }
1082    
1083     /*** マウスイベントを、Loggerのイベントに変換する ***/
1084    
1085     private var _drawing:Boolean = false; // 描画中かどうか
1086     private var _handtoolScrollBase:Point; // ハンドツールのつかみ元
1087     private var _fromPoint:Point; // 直線ツールの開始点
1088     private var _drawedLine:Boolean; // マウスクリックでドットを描くための、moveToしたあとに直線描画したかどうかのフラグ
1089
1090         // マウス座標から描画座標に変換。
1091         private static function zz(n:Number):Number {
1092           return Math.floor(n) + 0.5;
1093         }
1094         // マウス座標の描画座標での比較
1095         public static function comparePoint(ax:Number, ay:Number, bx:Number, by:Number):Boolean {
1096           return (zz(ax) == zz(bx) && zz(ay) == zz(by));
1097         }
1098    
1099     public function mouseDown(evt:MouseEvent):void {
1100       switch (_pen.mode) {
1101       case GPPen.PEN_MODE_HAND:
1102       case GPPen.PEN_MODE_ERASER:
1103         // moveToして、ペンの状態を設定し、ペンの状態変化をログし、始点の座標を覚えさせる
1104         // FIXME: lintToまでmoveToを遅延させよう!
1105         if (!_layerArray.isTargetLayerVisible) {
1106           Alert.show('不可視の状態では描画できません!', '手書き/消しゴムツール');
1107           return;
1108         }
1109         if (_layerArray.isTargetLayerLocked) {
1110           Alert.show('ロックされています!', '手書き/消しゴムツール');
1111           return;
1112         }
1113         _drawing = true;
1114         this.eventMoveTo(evt.localX, evt.localY);
1115         break;
1116       case GPPen.PEN_MODE_LINE:
1117       case GPPen.PEN_MODE_RECT:
1118       case GPPen.PEN_MODE_ELLIPSE:
1119       case GPPen.PEN_MODE_ROUND_RECT:
1120         if (!_layerArray.isTargetLayerVisible) {
1121           Alert.show('不可視の状態では描画できません!', '描画ツール');
1122           return;
1123         }
1124         if (_layerArray.isTargetLayerLocked) {
1125           Alert.show('ロックされています!', '描画ツール');
1126           return;
1127         }
1128         _fromPoint = new Point(evt.localX, evt.localY);
1129         _drawing = true;
1130        
1131         // 描画用
1132         invokeInsertDrawLayer();
1133         break;
1134       case GPPen.PEN_MODE_HANDTOOL:
1135         if (_canvasWindow) {
1136           _fromPoint = new Point(evt.localX, evt.localY);
1137           _handtoolScrollBase = _canvasWindow.canvasScrollPosition;
1138         }
1139         break;
1140       case GPPen.PEN_MODE_DROPPER:
1141         invokePenTempChange(_pen.mode, _layerArray.getColor(evt.localX, evt.localY), _pen.alpha, _pen.thickness);
1142         break;
1143       case GPPen.PEN_MODE_FLOOD_FILL:
1144         if (!_layerArray.isTargetLayerVisible) {
1145           Alert.show('不可視の状態では描画できません!', 'バケツツール');
1146           return;
1147         }
1148         if (_layerArray.isTargetLayerLocked) {
1149           Alert.show('ロックされています!', 'バケツツール');
1150           return;
1151         }
1152         this.eventMoveTo(evt.localX, evt.localY);
1153         this.eventFloodFill();
1154         break;
1155       case GPPen.PEN_MODE_PIXEL:
1156         if (!_layerArray.isTargetLayerVisible) {
1157           Alert.show('不可視の状態では描画できません!', 'ドット絵ツール');
1158           return;
1159         }
1160         if (_layerArray.isTargetLayerLocked) {
1161           Alert.show('ロックされています!', 'ドット絵ツール');
1162           return;
1163         }
1164         this.eventSetPixel(evt.localX, evt.localY);
1165         _drawing = true;
1166         break;
1167       }
1168     }
1169
1170     public function mouseMove(evt:MouseEvent):void {
1171       if (_canvasWindow) {
1172         var st:String = '座標(' + uint(evt.localX) + ', ' + uint(evt.localY) + ')';
1173         var col:uint = _layerArray.getColor32(evt.localX, evt.localY);
1174         st += ' 不透明度:' + (new Number((col >> 24) & 0xFF) / 255).toPrecision(2);
1175         st += ' 色:(' + ((col >> 16) & 0xFF) + ',' + ((col >> 8) & 0xFF) + ',' + (col & 0xFF) + ')';
1176         _canvasWindow.statusText = st;
1177       }
1178      
1179       if (evt.buttonDown) {
1180         switch (_pen.mode) {
1181         case GPPen.PEN_MODE_HAND:
1182         case GPPen.PEN_MODE_ERASER:
1183           if (_drawing) {
1184             this.eventLineTo(evt.localX, evt.localY);
1185           }
1186           break;
1187         case GPPen.PEN_MODE_DROPPER:
1188           invokePenTempChange(_pen.mode, _layerArray.getColor(evt.localX, evt.localY), _pen.alpha, _pen.thickness);
1189           break;
1190         case GPPen.PEN_MODE_HANDTOOL:
1191           if (_canvasWindow && _handtoolScrollBase) {
1192             _canvasWindow.scrollCanvas(_handtoolScrollBase.x + (_fromPoint.x - evt.localX),
1193                                        _handtoolScrollBase.y + (_fromPoint.y - evt.localY));
1194             //trace('base x:' + scrollBase.x + ' y:' + scrollBase.y + ' from x:' + fromPoint.x + ' y:' + fromPoint.y + ' local x:' + evt.localX + ' y:' + evt.localY + ' diff x:' + (fromPoint.x - evt.localX) + ' y:' + (fromPoint.y - evt.localY));           
1195           }
1196           break;
1197         case GPPen.PEN_MODE_LINE:
1198           if (_drawing) {
1199             _pen.previewLineTo(_fromPoint.x, _fromPoint.y, evt.localX, evt.localY);
1200           }
1201           break;
1202         case GPPen.PEN_MODE_PIXEL:
1203           if (_drawing) {
1204             this.eventSetPixel(evt.localX, evt.localY);
1205           }
1206           break;
1207         }
1208       }
1209     }
1210     public function mouseUp(evt:MouseEvent):void {
1211       switch (_pen.mode) {
1212       case GPPen.PEN_MODE_HAND:
1213       case GPPen.PEN_MODE_ERASER:
1214         if (_drawing) {
1215           if (!_drawedLine) {
1216             // 線の透明度は00にして、塗りの透明度に線の透明度を適用する。
1217             var tmpAlpha:Number = _pen.alpha;
1218             this.eventLineStyleAlpha(0);
1219             this.eventBeginFill(_pen.color, tmpAlpha);
1220             this.eventDrawCircle(_pen.thickness / 2);
1221             this.eventEndFill();
1222             this.eventLineStyleAlpha(tmpAlpha);
1223           }
1224           this.eventDrawShapeOnBitmap();
1225           _drawing = false;
1226         }
1227         break;
1228       case GPPen.PEN_MODE_LINE:
1229         if (_drawing) {
1230           invokeRemoveDrawLayer();
1231           if (!comparePoint(_fromPoint.x, _fromPoint.y, evt.localX, evt.localY)) {
1232             // 始点と終点が違う場合にのみ線を引く
1233             this.eventMoveTo(_fromPoint.x, _fromPoint.y);
1234             this.eventLineTo(evt.localX, evt.localY);
1235             this.eventDrawShapeOnBitmap();         
1236           }
1237           _drawing = false;
1238         }
1239         break;
1240       case GPPen.PEN_MODE_DROPPER:
1241         this.eventLineStyleColor(_layerArray.getColor(evt.localX, evt.localY));
1242         invokePenChange();
1243         invokePenCancelTool();
1244         break;
1245       case GPPen.PEN_MODE_HANDTOOL:
1246         _handtoolScrollBase = null;
1247         break;
1248       case GPPen.PEN_MODE_PIXEL:
1249         _drawing = false;
1250         break;
1251       }
1252     }
1253    
1254     // stage全体でmouseUpがあった場合。
1255     // mouseUpと二重で呼ばれる場合があるので注意
1256     public function extMouseUp(evt:MouseEvent):void {
1257     }
1258    
1259     public function mouseOut(evt:MouseEvent):void {
1260       switch (_pen.mode) {
1261       case GPPen.PEN_MODE_HAND:
1262       case GPPen.PEN_MODE_ERASER:
1263       case GPPen.PEN_MODE_PIXEL:
1264         if (_drawing) {
1265           mouseUp(evt);
1266         }
1267         break;
1268       case GPPen.PEN_MODE_DROPPER:
1269         invokePenChange();
1270         invokePenCancelTool();
1271         break;
1272       case GPPen.PEN_MODE_LINE:
1273         if (_drawing) {
1274           _drawing = false;
1275           invokeRemoveDrawLayer();
1276         }
1277         break;
1278       }
1279     }
1280     // イベントハンドラおわり
1281     public function get canvas():GPCanvas {
1282       return _canvas;
1283     }
1284     public function get logCount():uint {
1285       return _logCount;
1286     }
1287     public function get layerArray():GPLayerArray {
1288       return _layerArray;
1289     }
1290     public function get baseInfo():Object {
1291       return _baseInfo;
1292     }
1293   }
1294 }
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。