root/as3/gunyarapaint/branches/gunyarapaint/framework/src/org/libspark/gunyarapaint/framework/Painter.as

リビジョン 3488, 13.5 kB (コミッタ: hkrn, コミット時期: 3 年 前)

added 3 methods and use LayerBitmap#applyMatrix? instead of setting transform property

Line 
1 package org.libspark.gunyarapaint.framework
2 {
3     import flash.display.BitmapData;
4     import flash.display.BlendMode;
5     import flash.display.Sprite;
6     import flash.geom.Matrix;
7     import flash.geom.Point;
8     import flash.geom.Rectangle;
9
10     public class Painter
11     {
12         public function Painter(width:int, height:int, engine:PaintEngine)
13         {
14             m_paintEngine = engine;
15             m_layers = new LayerBitmapCollection(width, height);
16             m_altDrawingSprite = null;
17             m_horizontalMirrorMatrix = new Matrix(-1, 0, 0, 1, width, 0);
18             m_verticalMirrorMatrix = new Matrix(1, 0, 0, -1, 0, height);
19         }
20        
21         /**
22          * 連結されたレイヤー画像とメタデータから復元する
23          *
24          * @param layerBitmaps 縦に連結されたレイヤー画像
25          * @param metadata メタデータ
26          */
27         public function restore(layerBitmaps:BitmapData, metadata:Object):void
28         {
29             var width:uint = metadata.width;
30             var height:uint = metadata.height;
31             var layerCount:uint = layerBitmaps.height / height;
32             var destination:Point = new Point(0, 0);
33             var rectangle:Rectangle = new Rectangle(0, 0, width, height);
34             var sprite:Sprite = m_layers.spriteToView;
35             m_layers.clear();
36             for (var i:uint = 0; i < layerCount; i++) {
37                 var bitmapData:BitmapData = new BitmapData(width, height);
38                 bitmapData.copyPixels(layerBitmaps, rectangle, destination);
39                 rectangle.y = i * height;
40                 var layerBitmap:LayerBitmap = new LayerBitmap(bitmapData);
41                 m_layers.layers.push(layerBitmap);
42                 sprite.addChild(layerBitmap);
43             }
44         }
45        
46         /**
47          * 現在位置を変更する
48          *
49          * PainterEngine クラスにある moveTo の委譲
50          *
51          * @param x 移動先となる X 座標
52          * @param y 移動先となる Y 座標
53          */
54         public function moveTo(x:Number, y:Number):void
55         {
56             m_paintEngine.moveTo(roundPixel(x), roundPixel(y));
57         }
58        
59         /**
60          * 現在位置から指定された位置まで線を描写する
61          *
62          * PainterEngine クラスにある lineTo の委譲
63          *
64          * @param x 描写先となる X 座標
65          * @param y 描写先となる Y 座標
66          */
67         public function lineTo(x:Number, y:Number):void
68         {
69             m_paintEngine.lineTo(roundPixel(x), roundPixel(y));
70         }
71        
72         /**
73          * 矩形を描写する
74          *
75          * PainterEngine クラスにある drawRect の委譲
76          *
77          * @param x 基準点となる X 座標
78          * @param y 基準点となる Y 座標
79          * @param width 幅
80          * @param height 高さ
81          */
82         public function drawRect(x:Number, y:Number,
83                                  width:uint, height:uint):void
84         {
85             m_paintEngine.drawRect(x, y, width, height);
86         }
87        
88         /**
89          * 楕円を描写する
90          *
91          * PainterEngine クラスにある drawEllipse の委譲
92          *
93          * @param x 基準点となる X 座標
94          * @param y 基準点となる Y 座標
95          * @param width 幅
96          * @param height 高さ
97          */
98         public function drawEllipse(x:Number, y:Number,
99                                     width:uint, height:uint):void
100         {
101             m_paintEngine.drawEllipse(x, y, width, height);
102         }
103        
104         /**
105          * 塗りつぶしを開始する
106          *
107          * PainterEngine クラスにある beginFill の委譲
108          *
109          * @param color 塗りつぶす色
110          * @param alpha 透明度
111          */
112         public function beginFill(color:uint, alpha:Number):void
113         {
114             m_paintEngine.beginFill(color, alpha);
115         }
116        
117         /**
118          * 現在の位置から円弧を描写する
119          *
120          * PainterEngine クラスにある drawCircle の委譲
121          *
122          * @param radius 半径
123          */
124         public function drawCircle(radius:Number):void
125         {
126             m_paintEngine.drawCircle(radius);
127         }
128        
129         /**
130          * 塗りつぶしを終了する
131          *
132          * PainterEngine クラスにある endFill の委譲
133          *
134          */
135         public function endFill():void
136         {
137             m_paintEngine.endFill();
138         }
139        
140         public function resetPen():void
141         {
142             m_paintEngine.resetPen();
143         }
144        
145         public function clear():void
146         {
147             m_paintEngine.clear();
148         }
149        
150         /**
151          * PainterEngine クラスに描写された中身を現在のレイヤーに反映させる
152          *
153          *  Pen クラスのブレンドモードを適用する
154          *
155          */
156         public function composite():void
157         {
158             // undoBuffer に入っているLayerBitmapを上書きしない為にコピーしてから作業する
159             // これは floodFill 及び setPixel も同様
160             var newLayer:LayerBitmap = m_layers.currentLayer.clone();
161             newLayer.compositeFrom(
162                 m_paintEngine.shape,
163                 m_paintEngine.pen.blendMode
164             );
165             m_layers.setCurrentLayer(newLayer);
166             m_layers.compositeAll();
167         }
168        
169         /**
170          * 塗りつぶしを行う
171          *
172          * PainterEngine クラスの現在位置と Pen クラスの色を適用する
173          *
174          */
175         public function floodFill():void
176         {
177             var newLayer:LayerBitmap = m_layers.currentLayer.clone();
178             newLayer.floodFill(
179                 m_paintEngine.x,
180                 m_paintEngine.y,
181                 m_paintEngine.pen.argb
182             );
183             m_layers.setCurrentLayer(newLayer);
184             m_layers.compositeAll();
185         }
186        
187         /**
188          * 1 ピクセルを描写する
189          *
190          * 現在の Pen クラスの色を適用する
191          *
192          * @param x 描写先となる X 座標
193          * @param y 描写先となる Y 座標
194          */
195         public function setPixel(x:int, y:int):void
196         {
197             var newLayer:LayerBitmap = m_layers.currentLayer.clone();
198             newLayer.setPixel(x, y, m_paintEngine.pen.argb);
199             m_layers.setCurrentLayer(newLayer);
200             m_layers.compositeAll();
201         }
202        
203         /**
204          * 特定のピクセルの色を取得する(不透明度は取得しない)
205          *
206          * @param x 取得先となる X 座標
207          * @param y 取得先となる Y 座標
208          * @return RGB 形式の色の値
209          */
210         public function getPixel(x:int, y:int):uint
211         {
212             // AAAARRRRGGGGBBBB
213             var alpha:uint = m_layers.composited.getPixel32(x, y) >> 24 && 0xff;
214             return alpha > 0 ? m_layers.composited.getPixel(x, y) : 0xffffff;
215         }
216        
217         /**
218          * 特定のピクセルの色を取得する
219          *
220          * @param x 取得先となる X 座標
221          * @param y 取得先となる Y 座標
222          * @return ARGB 形式の色の値
223          */
224         public function getPixel32(x:int, y:int):uint
225         {
226             return layers.composited.getPixel32(x, y);
227         }
228        
229         /**
230          * レイヤーの可視状態を変更する
231          *
232          * @param index レイヤー番号
233          * @param visible 可視であるかどうか
234          */
235         public function setVisibleAt(index:int, visible:Boolean):void
236         {
237             m_layers[index].visible = visible;
238             m_layers.compositeAll();
239         }
240        
241         public function transformWithHorizontalMirrorAt(index:int):void
242         {
243             transformFromMatrixAt(index, m_horizontalMirrorMatrix);
244         }
245        
246         public function transformWithVerticalMirrorAt(index:int):void
247         {
248             transformFromMatrixAt(index, m_verticalMirrorMatrix);
249         }
250        
251         /**
252          * 描写開始を宣言する
253          *
254          * 全てのレイヤーに対してではなく、現在のレイヤーのみにブレンドモードが
255          * 適用されるように Sprite の変更が行われる。
256          */
257         public function startDrawingSession():void
258         {
259             if (m_altDrawingSprite === null) {
260                 m_paintEngine.resetPen();
261                 var currentLayer:LayerBitmap = m_layers.currentLayer;
262                 var blendMode:String = currentLayer.blendMode;
263                 m_altDrawingSprite = new Sprite();
264                 m_altDrawingSprite.mouseEnabled = false;
265                 m_altDrawingSprite.blendMode =
266                     blendMode == BlendMode.NORMAL ? BlendMode.LAYER : blendMode;
267                 m_altDrawingSprite.alpha = currentLayer.alpha;
268                 var tempLayer:LayerBitmap = currentLayer.clone(false);
269                 tempLayer.blendMode = BlendMode.NORMAL;
270                 tempLayer.alpha = 1.0;
271                 m_altDrawingSprite.addChild(tempLayer);
272                 m_altDrawingSprite.addChild(m_paintEngine.shape);
273                 var sprite:Sprite = m_layers.spriteToView;
274                 sprite.removeChild(currentLayer);
275                 sprite.addChildAt(m_altDrawingSprite, m_layers.currentIndex);
276             }
277         }
278        
279         /**
280          * 描写終了を宣言する
281          *
282          */
283         public function stopDrawingSession():void
284         {
285             if (m_altDrawingSprite !== null) {
286                 var sprite:Sprite = m_layers.spriteToView;
287                 var currentLayer:LayerBitmap = m_layers.currentLayer;
288                 var blendMode:String = m_altDrawingSprite.blendMode;
289                 currentLayer.blendMode =
290                     blendMode == BlendMode.LAYER ? BlendMode.NORMAL : blendMode;
291                 currentLayer.alpha = m_altDrawingSprite.alpha;
292                 sprite.removeChild(m_altDrawingSprite);
293                 sprite.addChildAt(currentLayer, m_layers.currentIndex);
294                 m_altDrawingSprite = null;
295                 m_paintEngine.clear();
296             }
297         }
298        
299         /**
300          * 現在のピクセルを補正する
301          *
302          * @param n ピクセル位置
303          * @return 補正したピクセル
304          */       
305         public function roundPixel(n:Number):Number
306         {
307             return n;
308         }
309        
310         private function transformFromMatrixAt(index:int, matrix:Matrix):void
311         {
312             if (index === 0xff) {
313                 var c:uint = m_layers.count;
314                 for (var i:uint = 0; i < c; i++) {
315                     m_layers.at(i).applyMatrix(matrix);
316                 }
317             }
318             else {
319                 m_layers.currentLayer.applyMatrix(matrix);
320             }
321             m_layers.compositeAll();
322         }
323        
324         private function saveUndo():Object
325         {
326             var count:uint = m_layers.count;
327             var layers:Vector.<LayerBitmap> = new Vector.<LayerBitmap>(
328                 count, true
329             );
330             for (var i:uint = 0; i < count; i++) {
331                 var layer:LayerBitmap = m_layers.layers[i].clone(false);
332                 layers[i] = layer;
333             }
334             var undoData:Object = {};
335             undoData.index = m_layers.currentIndex;
336             undoData.layers = layers;
337             return undoData;
338         }
339        
340         private function restoreUndo(undoData:Object):void
341         {
342             var i:uint = 0;
343             m_layers.clear();
344             var count:uint = undoData.layers.length;
345             var sprite:Sprite = m_layers.spriteToView;
346             for (i = 0; i < count; i++) {
347                 var layer:LayerBitmap = undoData.layers[i].clone(false);
348                 m_layers.layers.push(layer);
349                 sprite.addChild(layer);
350             }
351             m_layers.currentIndex = undoData.index;
352             m_layers.compositeAll();
353         }
354        
355         public function get layers():LayerBitmapCollection
356         {
357             return m_layers;
358         }
359        
360         public function get view():Sprite
361         {
362             return m_layers.spriteToView;
363         }
364        
365         public function get pen():Pen
366         {
367             return m_paintEngine.pen;
368         }
369        
370         /**
371          * 現在のレイヤーの透明度を変更する
372          *
373          * @param value
374          */
375         public function set currentLayerAlpha(value:Number):void
376         {
377             m_layers.currentLayer.alpha = value;
378             m_layers.compositeAll();
379         }
380        
381         /**
382          * 現在のブレンドモードを変更する
383          *
384          * @param value
385          */
386         public function set currentLayerBlendMode(value:String):void
387         {
388             m_layers.currentLayer.blendMode = value;
389             m_layers.compositeAll();
390         }
391        
392         public function set pen(value:Pen):void
393         {
394             m_paintEngine.pen = value;
395         }
396        
397         internal function get undo():Object
398         {
399             return saveUndo();
400         }
401        
402         internal function set undo(value:Object):void
403         {
404             restoreUndo(value);
405         }
406        
407         protected var m_paintEngine:PaintEngine;
408         protected var m_layers:LayerBitmapCollection;
409         private var m_horizontalMirrorMatrix:Matrix;
410         private var m_verticalMirrorMatrix:Matrix;
411         private var m_altDrawingSprite:Sprite;
412         private var m_shouldCopyBitmap:Boolean;
413     }
414 }
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。