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

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

release 2008100401

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:':
125       case '0.0.3:':
126       case '0.0.4:':
127       case '0.0.5:':
128         break;
129       default:
130         Alert('このバージョンのログには対応しておりません。ブラウザをリロードしてみてください。');
131         return null;
132       }
133       ret.createCanvas();
134       return ret;
135     }
136    
137     // 描画用
138     public static function createForDraw(width:uint, height:uint,
139                                          undoBufferSize:uint,
140                                          baseLayers:BitmapData,
141                                          baseInfo:Object
142                                         ):GPLogger {
143       var log:ByteArray = new ByteArray();
144       log.endian = flash.utils.Endian.BIG_ENDIAN;
145       log.writeUTFBytes('GUNYARA_PAINT:0.0.5:');
146       log.writeShort(width);
147       log.writeShort(height);
148       log.writeShort(undoBufferSize);
149       var ret:GPLogger = new GPLogger(log, true, width, height, undoBufferSize, baseLayers, baseInfo);
150       ret.createCanvas();
151       // 初期のペン状態を記録しておく。
152       ret.eventLineStyleThickness(ret._pen.thickness);
153       ret.eventLineStyleColor(ret._pen.color);
154       ret.eventLineStyleAlpha(ret._pen.alpha);
155       ret.eventLineStyleBlendMode(ret._pen.blendMode);
156       ret.eventLineStyleScaleMode(ret._pen.scaleMode);
157       ret.eventLineStyleCapsStyle(ret._pen.capsStyle);
158       ret.eventLineStyleJointStyle(ret._pen.jointStyle);
159       ret.eventLineStyleMiterLimit(ret._pen.miterLimit);
160       ret.eventLineStylePixelHinting(ret._pen.pixelHinting);
161
162       return ret;
163     }
164
165
166     // ACTIONは6bit長 0x3fまで
167     public static const ACTION_NONE:uint = 0;
168     public static const ACTION_MOVETO:uint = 1;
169     public static const ACTION_LINETO:uint = 2;
170     public static const ACTION_LINESTYLE:uint = 3;
171     public static const ACTION_DRAW_SHAPE_ON_BITMAP:uint = 4;
172     public static const ACTION_UNDO:uint = 5;
173     public static const ACTION_REDO:uint = 6;
174     public static const ACTION_BEGIN_FILL:uint = 7;
175     public static const ACTION_END_FILL:uint = 8;
176     public static const ACTION_DRAW_RECT:uint = 9;
177     public static const ACTION_DRAW_CIRCLE:uint = 10;
178     public static const ACTION_DRAW_ELLIPSE:uint = 11;
179     public static const ACTION_DRAW_ROUND_RECT:uint = 12;
180     public static const ACTION_FLOOD_FILL:uint = 13;
181     public static const ACTION_LAYER_NEW:uint = 14;
182     public static const ACTION_LAYER_COPY:uint = 15;
183     public static const ACTION_LAYER_SWAP:uint = 16;
184     public static const ACTION_LAYER_MERGE_WITH_BELOW:uint = 17;
185     public static const ACTION_LAYER_REMOVE:uint = 18;
186     public static const ACTION_LAYER_CHANGE_TARGET:uint = 19;
187     public static const ACTION_LAYER_CHANGE_VISIBLE:uint = 20;
188     public static const ACTION_LAYER_CHANGE_BLEND_MODE:uint = 21;
189     public static const ACTION_LAYER_CHANGE_ALPHA:uint = 22;
190
191     // LINESTYLE
192     public static const LINESTYLE_THICKNESS:uint = 1;
193     public static const LINESTYLE_COLOR:uint = 2;
194     public static const LINESTYLE_ALPHA:uint = 3;
195     public static const LINESTYLE_BLEND_MODE:uint = 4;
196     public static const LINESTYLE_SCALE_MODE:uint = 5;
197     public static const LINESTYLE_CAPS:uint = 6;
198     public static const LINESTYLE_JOINTS:uint = 7;
199     public static const LINESTYLE_MITER_LIMIT:uint = 8;
200     public static const LINESTYLE_PIXEL_HINTING:uint = 9; // NB: not used! first version, this is true
201
202     private var _pen:GPPen;
203     private var _layerArray:GPLayerArray;
204     private var _undoBuffer:GPUndoBuffer;
205
206     private function pushUndoBuffer():void {
207       _undoBuffer.push(_layerArray);
208       _changeUndoRedoHandler(_undoBuffer.undoCount, _undoBuffer.redoCount);
209     }
210
211     public function drawShapeOnBitmap():void {
212       // 描画
213       _layerArray.draw(_pen.drawShape, null, null, _pen.blendMode, null, false);
214       pushUndoBuffer();
215       invokeRemoveDrawLayer();
216     }
217    
218     private function invokeInsertDrawLayer():void {
219       _pen.setLineStyle();
220       _layerArray.insertDrawLayer(_pen.drawShape, _pen);     
221     }
222    
223     private function invokeRemoveDrawLayer():void {
224       _layerArray.removeDrawLayer(_pen.drawShape);
225       _pen.clearDrawShape();
226     }
227
228     /** log write **/
229
230     private function writeByte(byte:int):void {
231       _log.writeByte(byte);
232     }
233     private function writeShort(value:int):void {
234       _log.writeShort(value);
235     }
236     private function writeUInt(value:uint):void {
237       _log.writeUnsignedInt(value);
238     }
239     private function writeDouble(value:Number):void {
240       _log.writeDouble(value);
241     }
242     private function writeUTF(value:String):void {
243       _log.writeUTF(value);
244     }
245     private function writeBoolean(value:Boolean):void {
246       _log.writeByte(value ? 1 : 0);
247     }
248     private function readByte():uint {
249       return _log.readUnsignedByte();
250     }
251     private function readShort():int {
252       return _log.readShort();
253     }
254     private function readUShort():uint {
255       return uint(_log.readShort() & 0xffff);
256     }
257     private function readUInt():uint {
258       return _log.readUnsignedInt();
259     }
260     private function readDouble():Number {
261       return _log.readDouble();
262     }
263     private function readUTF():String {
264       return _log.readUTF();
265     }
266     private function readBoolean():Boolean {
267       return (_log.readByte() == 1);
268     }
269
270     // ログ関係のローカル変数
271     private var _playLogIntervalId:uint;
272     private var _playSpeed:uint;
273
274     public function set playSpeed(speed:uint):void {
275       _playSpeed = speed;
276     }
277    
278     private var _playCompleteCallback:Function;
279
280     public function play(speed:uint, callback:Function):void {
281       _playSpeed = speed;
282       _playCompleteCallback = callback;
283       _playLogIntervalId = flash.utils.setInterval(playNext, 50);
284     }
285
286     private var _preAction:uint = ACTION_NONE; // for avoid version 0.0.1 bug...◆
287     private function playNext():void {
288       for (var i:uint = 0; i < _playSpeed; i++) {
289         if (!read()) {
290           flash.utils.clearInterval(_playLogIntervalId);
291           _playCompleteCallback();
292           break;
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         default:
436           if (byte & 0x80) {
437             if (byte & 0x40) {
438               // 7bit lineTo
439               _log.position -= 1;
440               short = readShort();
441               dx = (short << 18) >> 25;
442               dy = (short << 25) >> 25;
443             } else {
444               // 3bit lineTo
445               dx = (byte << 26) >> 29;
446               dy = (byte << 29) >> 29;
447             }
448             preX += dx;
449             preY += dy;
450             eventLineTo(preX, preY);
451           } else if (byte & 0x40) {
452             // 7bit moveTo
453             _log.position -= 1;
454             short = readShort();
455             dx = (short << 18) >> 25;
456             dy = (short << 25) >> 25;
457             preX += dx;
458             preY += dy;
459             eventMoveTo(preX, preY);
460           } else {
461             Alert.show('未対応のアクションです。');
462             // error
463           }
464         }
465         _preAction = byte;
466         return true;
467       } catch (e:EOFError) {
468       }
469       return false;
470     }
471
472     public function resetInstance():void {
473       _log.position = _startLogPosition;
474       preX = 0; preY = 0; _logCount = 0;
475     }
476
477     public function get password():String {
478       var pos:uint = _log.position;
479       var e:Base64Encoder = new Base64Encoder();
480       _log.compress();
481       e.encodeBytes(_log);
482       _log.uncompress();
483       _log.position = pos;
484       return e.flush();
485     }
486    
487     public static function deserialize(s:String,
488                                        changeImageCallback:Function,
489                                        undoRedoCallback:Function,
490                                        baseLayers:BitmapData,
491                                        baseInfo:Object
492                                       ):GPLogger {
493       var e:Base64Decoder = new Base64Decoder();
494       e.decode(s);
495       var b:ByteArray = e.toByteArray();
496       b.uncompress();
497       return createFromByteArray(b, true, baseLayers, baseInfo);
498     }
499
500     /**********************************************/
501     /* 新メソッド */
502     private var _preX:int, _preY:int; // ログで差分エンコードするときに必要な直線のmoveTo/lineToの値
503     private var _onLogging:Boolean = false; // ログ取得中かどうか
504    
505     private var _drawApplication:Application;
506     private var _canvasWindow:GPCanvasWindowControl;
507     private var _penWindow:PenDetailWindowControl;
508     private var _layerWindow:GPLayerWindowControl;
509
510     public function eventMoveTo(x:Number, y:Number):void {
511       var ix:int = Math.floor(x);
512       var iy:int = Math.floor(y);
513       if (_onLogging) {
514         var dx:int = ix - _preX;
515         var dy:int = iy - _preY;
516         if (dx >= -64 && dx <= 63 && dy >= -64 && dy <= 63) {
517           // dxもdyも7bitに収まる場合
518           writeShort(0x4000 | (dx << 7) & 0x3f80 | dy & 0x7f);
519         } else {
520           writeByte(ACTION_MOVETO);
521           writeShort(dx);
522           writeShort(dy);
523         }
524         _preX = ix;
525         _preY = iy;
526         _logCount++;
527       }
528       _pen.moveTo(ix, iy);
529       trace('MOVE_TO x:' + ix + ' y:' + iy);
530      
531       invokeInsertDrawLayer();
532     }
533    
534     public function eventLineTo(x:Number, y:Number):void {
535       var ix:int = Math.floor(x);
536       var iy:int = Math.floor(y);
537       if (_onLogging) {
538         var dx:int = ix - _preX;
539         var dy:int = iy - _preY;
540         if (dx >= -64 && dx <= 63 && dy >= -64 && dy <= 63) {
541           // dxもdyも7bitに収まる場合
542           writeShort(0xc000 | (dx << 7) & 0x3f80 | dy & 0x7f);
543         } else {
544           writeByte(ACTION_LINETO);
545           writeShort(dx);
546           writeShort(dy);
547         }
548         _preX = ix;
549         _preY = iy;
550         _logCount++;
551       }
552       _pen.lineTo(ix, iy);
553       trace('LINE_TO x:' + ix + ' y:' + iy);
554     }
555    
556     private function invokePenChange():void {
557       if (_penWindow) {
558         _penWindow.changePen(_pen.mode, _pen.color, _pen.alpha, _pen.thickness);
559       }
560     }
561    
562     private function invokePenCancelTool():void {
563       if (_penWindow) {
564         _penWindow.cancelTool();
565       }
566     }
567
568     // 一時的にUIのみのペン状態を変える
569     private function invokePenTempChange(mode:uint, color:uint, alpha:Number, thickness:uint):void {
570       if (_penWindow) {
571         _penWindow.changePen(mode, color, alpha, thickness);
572       }     
573     }
574    
575     public function eventLineStyleThickness(thickness:uint):void {
576       if (_pen.thickness == thickness) {
577         return;
578       }
579       if (_onLogging) {
580         writeByte(ACTION_LINESTYLE);
581         writeByte(LINESTYLE_THICKNESS);
582         writeByte(thickness);
583         _logCount++;
584       }
585       _pen.thickness = thickness;
586       trace('LINE_STYLE thickness:' + thickness);
587
588       invokePenChange();
589     }
590    
591     public function eventLineStyleColor(rgbcolor:uint):void {
592       if (_pen.color == rgbcolor) {
593         return;
594       }
595       if (_onLogging) {
596         writeByte(ACTION_LINESTYLE);
597         writeByte(LINESTYLE_COLOR);
598         writeUInt(rgbcolor);
599         _logCount++;
600       }
601       _pen.color = rgbcolor;
602       trace('LINE_STYLE color:' + rgbcolor);
603
604       invokePenChange();
605     }
606    
607     public function eventLineStyleAlpha(alpha:Number):void {
608       if (_pen.alpha == alpha) {
609         return;
610       }
611       if (_onLogging) {
612         writeByte(ACTION_LINESTYLE);
613         writeByte(LINESTYLE_ALPHA);
614         writeDouble(alpha);
615         _logCount++;
616       }
617       _pen.alpha = alpha;
618       trace('LINE_STYLE alpha:' + alpha);
619
620       invokePenChange();
621     }
622    
623     public function eventLineStyleMiterLimit(miterLimit:Number):void {
624       if (_pen.miterLimit == miterLimit) {
625         return;
626       }
627       if (_onLogging) {
628         writeByte(ACTION_LINESTYLE);
629         writeByte(LINESTYLE_MITER_LIMIT);
630         writeDouble(miterLimit);
631         _logCount++;
632       }
633       _pen.miterLimit = miterLimit;
634       trace('LINE_STYLE miterLimit:' + miterLimit);
635
636       invokePenChange();
637     }
638    
639     public function eventLineStyleBlendMode(blendMode:String):void {
640       if (_pen.blendMode == blendMode) {
641         return;
642       }
643       if (_onLogging) {
644         writeByte(ACTION_LINESTYLE);
645         writeByte(LINESTYLE_BLEND_MODE);
646         writeUTF(blendMode);
647         _logCount++;
648       }
649       _pen.blendMode = blendMode;
650       trace('LINE_STYLE blendMode:' + blendMode);
651
652       invokePenChange();
653     }
654    
655     public function eventLineStyleScaleMode(scaleMode:String):void {
656       if (_pen.scaleMode == scaleMode) {
657         return;
658       }
659       if (_onLogging) {
660         writeByte(ACTION_LINESTYLE);
661         writeByte(LINESTYLE_SCALE_MODE);
662         writeUTF(scaleMode);
663         _logCount++;
664       }
665       _pen.scaleMode = scaleMode;
666       trace('LINE_STYLE scaleMode:' + scaleMode);
667
668       invokePenChange();
669     }
670    
671     public function eventLineStyleCapsStyle(capsStyle:String):void {
672       if (_pen.capsStyle == capsStyle) {
673         return;
674       }
675       if (_onLogging) {
676         writeByte(ACTION_LINESTYLE);
677         writeByte(LINESTYLE_CAPS);
678         writeUTF(capsStyle);
679         _logCount++;
680       }
681       _pen.capsStyle = capsStyle;
682       trace('LINE_STYLE capsStyle:' + capsStyle);
683
684       invokePenChange();
685     }
686    
687     public function eventLineStyleJointStyle(jointStyle:String):void {
688       if (_pen.jointStyle == jointStyle) {
689         return;
690       }
691       if (_onLogging) {
692         writeByte(ACTION_LINESTYLE);
693         writeByte(LINESTYLE_JOINTS);
694         writeUTF(jointStyle);
695         _logCount++;
696       }
697       _pen.jointStyle = jointStyle;
698       trace('LINE_STYLE jointStyle:' + jointStyle);
699
700       invokePenChange();
701     }
702    
703     public function eventLineStylePixelHinting(pixelHinting:Boolean):void {
704       if (_pen.pixelHinting == pixelHinting) {
705         return;
706       }
707       if (_onLogging) {
708         writeByte(ACTION_LINESTYLE);
709         writeByte(LINESTYLE_PIXEL_HINTING);
710         writeBoolean(pixelHinting);
711         _logCount++;
712       }
713       _pen.pixelHinting = pixelHinting;
714       trace('LINE_STYLE pixelHinting:' + pixelHinting);
715
716       invokePenChange();
717     }
718    
719     public function eventDrawShapeOnBitmap():void {
720       if (_onLogging) {
721         writeByte(ACTION_DRAW_SHAPE_ON_BITMAP);
722         _logCount++;
723       }
724       this.drawShapeOnBitmap();
725       trace('DRAW_SHAPE_ON_BITMAP');
726     }
727    
728     public function eventUndo():void {
729       var obj:Object = _undoBuffer.undo();
730       if (!obj) {
731         return;
732       }
733       if (_onLogging) {
734         writeByte(ACTION_UNDO);
735         _logCount++;
736       }
737       _layerArray.dataForUndo = obj;
738       _changeUndoRedoHandler(_undoBuffer.undoCount, _undoBuffer.redoCount);
739       invokeLayerChange();
740       trace('UNDO');
741     }
742    
743     public function eventRedo():void {
744       var obj:Object = _undoBuffer.redo();
745       if (!obj) {
746         return;
747       }
748       if (_onLogging) {
749         writeByte(ACTION_REDO);
750         _logCount++;
751       }
752       _layerArray.dataForUndo = obj;
753       _changeUndoRedoHandler(_undoBuffer.undoCount, _undoBuffer.redoCount);
754       invokeLayerChange();
755       trace('REDO');
756     }
757    
758     public function eventBeginFill(color:uint, alpha:Number):void {
759       if (_onLogging) {
760         writeByte(ACTION_BEGIN_FILL);
761         writeUInt(color);
762         writeDouble(alpha);
763         _logCount++;
764       }
765       _pen.beginFill(color, alpha);
766       trace('BEGIN_FILL color:'+ color + ' alpha:' + alpha);
767     }
768    
769     public function eventEndFill():void {
770       if (_onLogging) {
771         writeByte(ACTION_END_FILL);
772         _logCount++;
773       }
774       _pen.endFill();
775       trace('END_FILL');
776     }
777    
778     public function eventDrawCircle(radius:Number):void {
779       if (_onLogging) {
780         // 直前のmoveToの座標を中心。よって、半径のみ保存
781         writeByte(ACTION_DRAW_CIRCLE);
782         writeDouble(radius);
783         _logCount++;
784       }
785       _pen.drawCircle(radius);
786       trace('DRAW_CIRCLE radius:' + radius);
787     }
788    
789     public function eventFloodFill():void {
790       if (_onLogging) {
791         writeByte(ACTION_FLOOD_FILL);
792         _logCount++;
793       }
794       _pen.floodFill();
795       trace('FLOOD_FILL');
796     }
797
798     private function invokeLayerChange():void {
799       if (_layerWindow) {
800         _layerWindow.changeLayer();
801         _logCount++;
802       }
803       // _pen.setLineStyle();
804     }
805    
806     public function eventLayerNew():void {
807       if (!_layerArray.insertNew()) {
808         return;
809       }
810       if (_onLogging) {
811         writeByte(ACTION_LAYER_NEW);
812         _logCount++;
813       }
814       trace('LAYER_NEW');
815
816       pushUndoBuffer();
817       invokeLayerChange();
818     }
819    
820     public function eventLayerCopy():void {
821       if (!_layerArray.copy()) {
822         return;
823       }
824       if (_onLogging) {
825         writeByte(ACTION_LAYER_COPY);
826         _logCount++;
827       }
828       trace('LAYER_COPY');
829      
830       pushUndoBuffer();
831       invokeLayerChange();
832     }
833    
834     public function eventLayerSwap(fromIndex:uint, toIndex:uint):void {
835       if (!_layerArray.swap(fromIndex, toIndex)) {
836         return;
837       }
838       if (_onLogging) {
839         writeByte(ACTION_LAYER_SWAP);
840         writeByte(fromIndex);
841         writeByte(toIndex);
842         _logCount++;
843       }
844       trace('LAYER_SWAP from:' + fromIndex + ' to:' + toIndex);
845      
846       pushUndoBuffer();
847       invokeLayerChange();
848     }
849    
850     public function eventLayerMergeWithBelow():void {
851       if (!_layerArray.mergeWithBelow()) {
852         return;
853       }
854       if (_onLogging) {
855         writeByte(ACTION_LAYER_MERGE_WITH_BELOW);
856         _logCount++;
857       }
858       trace('LAYER_MERGE_WITH_BELOW');
859
860       pushUndoBuffer();
861       invokeLayerChange();
862     }
863    
864     public function eventLayerRemove():void {
865       if (!_layerArray.remove()) {
866         return;
867       }
868       if (_onLogging) {
869         writeByte(ACTION_LAYER_REMOVE);
870         _logCount++;
871       }
872       trace('LAYER_REMOVE');
873
874       pushUndoBuffer();
875       invokeLayerChange();
876     }
877    
878     public function eventLayerChangeTarget(target:uint):void {
879       if (_layerArray.targetIndex == target) {
880         return;
881       }
882       if (_onLogging) {
883         writeByte(ACTION_LAYER_CHANGE_TARGET);
884         writeByte(target);
885         _logCount++;
886       }
887       _layerArray.targetIndex = target;
888       trace('LAYER_CHANGE_TARGET target:' + target);
889
890       // UndoRedoには反映しない
891       invokeLayerChange();
892     }
893    
894     public function eventLayerChangeVisible(target:uint, visible:Boolean):void {
895       if (!_layerArray.changeVisible(target, visible)) {
896         return;
897       }
898       if (_onLogging) {
899         writeByte(ACTION_LAYER_CHANGE_VISIBLE);
900         writeByte(target);
901         writeBoolean(visible);
902         _logCount++;
903       }
904       trace('LAYER_CHANGE_VISIBLE target:' + target + ' value:' + visible);
905
906       // UndoRedoには反映しない
907       invokeLayerChange();
908     }
909    
910     public function eventLayerChangeBlendMode(blendMode:String):void {
911       if (_layerArray.targetLayerBlendMode == blendMode) {
912         return;
913       }
914       if (_onLogging) {
915         writeByte(ACTION_LAYER_CHANGE_BLEND_MODE);
916         writeUTF(blendMode);
917         _logCount++;
918       }
919       _layerArray.targetLayerBlendMode = blendMode;
920       trace('LAYER_CHANGE_BLEND_MODE blendMode:' + blendMode);
921
922       pushUndoBuffer();
923       invokeLayerChange();
924     }
925    
926     public function eventLayerChangeAlpha(alpha:Number):void {
927       if (_layerArray.targetLayerAlpha == alpha) {
928         return;
929       }
930       if (_onLogging) {
931         writeByte(ACTION_LAYER_CHANGE_ALPHA);
932         writeDouble(alpha);
933         _logCount++;
934       }
935       _layerArray.targetLayerAlpha = alpha;
936       trace('LAYER_CHANGE_ALPHA alpha:' + alpha);
937
938       pushUndoBuffer();
939       invokeLayerChange();
940     }
941    
942     // いまはログとってないイベントたち。
943
944     public function eventLayerChangeLock(target:uint, lock:Boolean):void {
945       if (!_layerArray.changeLock(target, lock)) {
946         return;
947       }
948       if (_onLogging) {
949         //
950       }
951       // trace('LAYER_CHANGE_LOCK target:' + target + ' value:' + lock);
952     }
953    
954     public function eventCanvasMove(x:uint, y:uint):void {
955       if (_onLogging) {
956         // logging
957       }
958       _canvas.move(x, y);
959       //trace('eventCanvasMove x:' + alpha);
960     }
961    
962     public function eventCanvasScale(scale:Number):void {
963       if (_onLogging) {
964         // logging
965       }
966       _canvas.scaleX = scale;
967       _canvas.scaleY = scale;
968       //trace('eventCanvasMove scale:' + alpha);
969     }
970
971     public function eventSetAdditionalNumber(num:uint):void {
972       if (_onLogging) {
973         // logging
974       }
975       _canvas.setAdditionalNumber(num);
976     }
977    
978     public function eventSetAdditionalBox(visible:Boolean):void {
979       if (_onLogging) {
980         // logging
981       }
982       _canvas.setAdditionalBox(visible);
983     }
984
985     public function eventSetAdditionalSkew(visible:Boolean):void {
986       if (_onLogging) {
987         // logging
988       }
989       _canvas.setAdditionalSkew(visible);
990     }
991    
992     public function eventSetPenMode(mode:uint):void {
993       if (_onLogging) {
994         // logging
995       }
996       _pen.mode = mode;
997
998       invokePenChange();
999
1000       if (_canvas) {
1001         switch (mode) {
1002         case GPPen.PEN_MODE_DROPPER:
1003           _canvas.setCursor(dropperIcon);
1004           break;
1005         case GPPen.PEN_MODE_HANDTOOL:
1006           _canvas.setCursor(handOpenIcon);
1007           break;
1008         case GPPen.PEN_MODE_ERASER:
1009            // FIXME: give me eraser icon
1010           _canvas.setCursor(null);
1011           break;
1012         case GPPen.PEN_MODE_PENCIL:
1013           // TODO: つくる。
1014           break;
1015         default:
1016           _canvas.setCursor(null);
1017         }
1018         if (mode == GPPen.PEN_MODE_DROPPER) {
1019         } else {
1020         }       
1021       }
1022     }
1023
1024     public function get dataForPost():Object {
1025       var o:Object = _layerArray.dataForPost;
1026       o['compressed_log'] = compressedLog;
1027       o['info']['log_count'] = _logCount;
1028       o['info']['undo_buffer_size'] = _undoBufferSize;
1029       if (_penWindow) {
1030         o['info']['pen_details'] = _penWindow.dataForPost;
1031       }
1032       return o;
1033     }
1034    
1035     public function get compressedLog():ByteArray {
1036       var cl:ByteArray = new ByteArray();
1037       var tempPos:uint = _log.position;
1038       _log.compress();
1039       cl.writeBytes(_log);
1040       _log.uncompress();
1041       _log.position = tempPos;
1042       return cl;
1043     }
1044    
1045     public function get canvasWidth():uint {
1046       return _canvasWidth;
1047     }
1048
1049     public function get canvasHeight():uint {
1050       return _canvasHeight;
1051     }
1052    
1053     public function get undoBufferSize():uint {
1054       return _undoBufferSize;
1055     }
1056    
1057     /*** マウスイベントを、Loggerのイベントに変換する ***/
1058    
1059     private var _drawing:Boolean = false; // 描画中かどうか
1060     private var _handtoolScrollBase:Point; // ハンドツールのつかみ元
1061     private var _fromPoint:Point; // 直線ツールの開始点
1062     private var _drawedLine:Boolean; // マウスクリックでドットを描くための、moveToしたあとに直線描画したかどうかのフラグ
1063
1064         // マウス座標から描画座標に変換。
1065         private static function zz(n:Number):Number {
1066           return Math.floor(n) + 0.5;
1067         }
1068         // マウス座標の描画座標での比較
1069         public static function comparePoint(ax:Number, ay:Number, bx:Number, by:Number):Boolean {
1070           return (zz(ax) == zz(bx) && zz(ay) == zz(by));
1071         }
1072    
1073     public function mouseDown(evt:MouseEvent):void {
1074       switch (_pen.mode) {
1075       case GPPen.PEN_MODE_HAND:
1076       case GPPen.PEN_MODE_ERASER:
1077         // moveToして、ペンの状態を設定し、ペンの状態変化をログし、始点の座標を覚えさせる
1078         // FIXME: lintToまでmoveToを遅延させよう!
1079         if (!_layerArray.isTargetLayerVisible) {
1080           Alert.show('不可視の状態では描画できません!', '手書き/消しゴムツール');
1081           return;
1082         }
1083         if (_layerArray.isTargetLayerLocked) {
1084           Alert.show('ロックされています!', '手書き/消しゴムツール');
1085           return;
1086         }
1087         _drawing = true;
1088         _drawedLine = false;
1089         this.eventMoveTo(evt.localX, evt.localY);
1090         break;
1091       case GPPen.PEN_MODE_LINE:
1092       case GPPen.PEN_MODE_RECT:
1093       case GPPen.PEN_MODE_ELLIPSE:
1094       case GPPen.PEN_MODE_ROUND_RECT:
1095         if (!_layerArray.isTargetLayerVisible) {
1096           Alert.show('不可視の状態では描画できません!', '描画ツール');
1097           return;
1098         }
1099         if (_layerArray.isTargetLayerLocked) {
1100           Alert.show('ロックされています!', '描画ツール');
1101           return;
1102         }
1103         _fromPoint = new Point(evt.localX, evt.localY);
1104         _drawing = true;
1105        
1106         // 描画用
1107         invokeInsertDrawLayer();
1108
1109         break;
1110       case GPPen.PEN_MODE_HANDTOOL:
1111         if (_canvasWindow) {
1112           _fromPoint = new Point(evt.localX, evt.localY);
1113           _handtoolScrollBase = _canvasWindow.canvasScrollPosition;
1114         }
1115         break;
1116       case GPPen.PEN_MODE_DROPPER:
1117         invokePenTempChange(_pen.mode, _layerArray.getColor(evt.localX, evt.localY), _pen.alpha, _pen.thickness);
1118         break;
1119       case GPPen.PEN_MODE_FLOOD_FILL:
1120         if (!_layerArray.isTargetLayerVisible) {
1121           Alert.show('不可視の状態では描画できません!', 'バケツツール');
1122           return;
1123         }
1124         if (_layerArray.isTargetLayerLocked) {
1125           Alert.show('ロックされています!', 'バケツツール');
1126           return;
1127         }
1128         this.eventMoveTo(evt.localX, evt.localY);
1129         this.eventFloodFill();
1130         break;
1131       case GPPen.PEN_MODE_PENCIL:
1132         // TODO: つくる。
1133         break;
1134       }
1135     }
1136
1137     public function mouseMove(evt:MouseEvent):void {
1138       if (_canvasWindow) {
1139         _canvasWindow.statusText = '座標(' + uint(evt.localX) + ', ' + uint(evt.localY) + ')';
1140       }
1141      
1142       if (evt.buttonDown) {
1143         switch (_pen.mode) {
1144         case GPPen.PEN_MODE_HAND:
1145         case GPPen.PEN_MODE_ERASER:
1146           if (_drawing) {
1147             this.eventLineTo(evt.localX, evt.localY);
1148             _drawedLine = true;
1149           }
1150           break;
1151         case GPPen.PEN_MODE_DROPPER:
1152           invokePenTempChange(_pen.mode, _layerArray.getColor(evt.localX, evt.localY), _pen.alpha, _pen.thickness);
1153           break;
1154         case GPPen.PEN_MODE_HANDTOOL:
1155           if (_canvasWindow && _handtoolScrollBase) {
1156             _canvasWindow.scrollCanvas(_handtoolScrollBase.x + (_fromPoint.x - evt.localX),
1157                                        _handtoolScrollBase.y + (_fromPoint.y - evt.localY));
1158             //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));           
1159           }
1160           break;
1161         case GPPen.PEN_MODE_LINE:
1162           if (_drawing) {
1163             _pen.previewLineTo(_fromPoint.x, _fromPoint.y, evt.localX, evt.localY);
1164           }
1165           break;
1166         case GPPen.PEN_MODE_PENCIL:
1167           // TODO: つくる。
1168           break;
1169         }
1170       }
1171     }
1172     public function mouseUp(evt:MouseEvent):void {
1173       switch (_pen.mode) {
1174       case GPPen.PEN_MODE_HAND:
1175       case GPPen.PEN_MODE_ERASER:
1176         if (_drawing) {
1177           if (!_drawedLine) {
1178             // 線の透明度は00にして、塗りの透明度に線の透明度を適用する。
1179             var tmpAlpha:Number = _pen.alpha;
1180             this.eventLineStyleAlpha(0);
1181             this.eventBeginFill(_pen.color, tmpAlpha);
1182             this.eventDrawCircle(_pen.thickness / 2);
1183             this.eventEndFill();
1184             this.eventLineStyleAlpha(tmpAlpha);
1185           }
1186           this.eventDrawShapeOnBitmap();
1187           _drawing = false;
1188         }
1189         break;
1190       case GPPen.PEN_MODE_LINE:
1191         if (_drawing) {
1192           invokeRemoveDrawLayer();
1193           if (!comparePoint(_fromPoint.x, _fromPoint.y, evt.localX, evt.localY)) {
1194             // 始点と終点が違う場合にのみ線を引く
1195             this.eventMoveTo(_fromPoint.x, _fromPoint.y);
1196             this.eventLineTo(evt.localX, evt.localY);
1197             this.eventDrawShapeOnBitmap();         
1198           }
1199           _drawing = false;
1200         }
1201         break;
1202       case GPPen.PEN_MODE_DROPPER:
1203         this.eventLineStyleColor(_layerArray.getColor(evt.localX, evt.localY));
1204         invokePenChange();
1205         invokePenCancelTool();
1206         break;
1207       case GPPen.PEN_MODE_HANDTOOL:
1208         _handtoolScrollBase = null;
1209         break;
1210       case GPPen.PEN_MODE_PENCIL:
1211         // TODO: つくる。
1212         break;
1213       }
1214     }
1215    
1216     // stage全体でmouseUpがあった場合。
1217     // mouseUpと二重で呼ばれる場合があるので注意
1218     public function extMouseUp(evt:MouseEvent):void {
1219     }
1220    
1221     public function mouseOut(evt:MouseEvent):void {
1222       switch (_pen.mode) {
1223       case GPPen.PEN_MODE_HAND:
1224       case GPPen.PEN_MODE_ERASER:
1225         if (_drawing) {
1226           mouseUp(evt);
1227         }
1228         break;
1229       case GPPen.PEN_MODE_DROPPER:
1230         invokePenChange();
1231         invokePenCancelTool();
1232         break;
1233       case GPPen.PEN_MODE_LINE:
1234         if (_drawing) {
1235           _drawing = false;
1236           invokeRemoveDrawLayer();
1237         }
1238         break;
1239       }
1240     }
1241     // イベントハンドラおわり
1242     public function get canvas():GPCanvas {
1243       return _canvas;
1244     }
1245     public function get logCount():uint {
1246       return _logCount;
1247     }
1248     public function get layerArray():GPLayerArray {
1249       return _layerArray;
1250     }
1251     public function get baseInfo():Object {
1252       return _baseInfo;
1253     }
1254   }
1255 }
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。