PageRenderTime 299ms CodeModel.GetById 107ms RepoModel.GetById 1ms app.codeStats 1ms

/test/js/cocktail/port/flash_player/DrawingManager.hx

http://github.com/lexoyo/hxtml2
Haxe | 487 lines | 254 code | 78 blank | 155 comment | 9 complexity | 0c727e801cbdad0756fc424307db9530 MD5 | raw file
  1. /*
  2. This file is part of Cocktail http://www.silexlabs.org/groups/labs/cocktail/
  3. This project is © 2010-2011 Silex Labs and is released under the GPL License:
  4. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (GPL) as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
  5. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  6. To read the license please visit http://www.gnu.org/copyleft/gpl.html
  7. */
  8. package cocktail.port.flash_player;
  9. import cocktail.core.NativeElement;
  10. import cocktail.core.drawing.AbstractDrawingManager;
  11. import flash.display.Bitmap;
  12. import flash.display.BitmapData;
  13. import flash.display.CapsStyle;
  14. import flash.display.GradientType;
  15. import flash.display.JointStyle;
  16. import flash.display.LineScaleMode;
  17. import flash.display.Sprite;
  18. import cocktail.core.geom.Matrix;
  19. import cocktail.core.dom.DOMData;
  20. import cocktail.core.geom.GeomData;
  21. import flash.geom.ColorTransform;
  22. import haxe.Log;
  23. /**
  24. * This is the Flash AVM2 implementation of the DrawingManager.
  25. * It draws shape programatically onto a native Sprite object.
  26. * The sprite HTMLElement is then cached as a bitmap. It allows to work
  27. * with both the flash vector drawing API and bitmaps.
  28. *
  29. * @author Yannick DOMINGUEZ
  30. */
  31. class DrawingManager extends AbstractDrawingManager
  32. {
  33. /**
  34. * a bitmap display object onto which
  35. * are drawn bitmap and/or rasterised
  36. * vector drawings
  37. */
  38. private var _bitmapDrawing:Bitmap;
  39. /**
  40. * Cast the nativeElement as a sprite to access the
  41. * graphics object
  42. */
  43. private var _typedNativeElement:Sprite;
  44. /**
  45. * class constructor. Init the background Sprite with
  46. * a default width and height. Add a bitmap display object that
  47. * will copy the vector drawing as they are drawn
  48. */
  49. public function new(nativeElement:NativeElement, width:Int, height:Int)
  50. {
  51. super(nativeElement, width, height);
  52. _typedNativeElement = cast(this._nativeElement);
  53. //init the bitmap display object and attach it to the display list
  54. _bitmapDrawing = new Bitmap(new BitmapData(_width, _height, true, 0x00000000));
  55. this._nativeElement.addChild(_bitmapDrawing);
  56. }
  57. //////////////////////////////////////////////////////////////////////////////////////////
  58. // Overriden fill control methods
  59. //////////////////////////////////////////////////////////////////////////////////////////
  60. /**
  61. * Ends a fill on the native Sprite's graphic object.
  62. * Convert the resulting vector into a bitmap
  63. */
  64. override public function endFill():Void
  65. {
  66. _typedNativeElement.graphics.endFill();
  67. blit();
  68. _typedNativeElement.graphics.clear();
  69. }
  70. /**
  71. * clear the vector and bitmap drawing
  72. */
  73. override public function clear():Void
  74. {
  75. _typedNativeElement.graphics.clear();
  76. _bitmapDrawing.bitmapData.fillRect(new flash.geom.Rectangle(0, 0, width, height), 0x00000000);
  77. }
  78. //////////////////////////////////////////////////////////////////////////////////////////
  79. // Private pixel manipulation method
  80. //////////////////////////////////////////////////////////////////////////////////////////
  81. /**
  82. * Turn the current drawn graphic object into a bitmap. Each graphic object is drawn
  83. * into the same bitmap as they are drawn (done on each call to the endFill method).
  84. */
  85. private function blit():Void
  86. {
  87. //create a new transparent bitmap data, the size of the vector drawing
  88. var currentGraphicBitmapData:BitmapData = new BitmapData(Math.round(_typedNativeElement.width), Math.round(_typedNativeElement.height), true, 0x00000000);
  89. //draw the current vector into a bitmap
  90. currentGraphicBitmapData.draw(_typedNativeElement);
  91. //retrive the current bitmapData (the sum of all the previous
  92. //vector drawings)
  93. var bitmapData:BitmapData = _bitmapDrawing.bitmapData;
  94. //copy each pixel from the new vector drawing into the current bitmapData,
  95. //preserving the alpha values
  96. bitmapData.copyPixels(currentGraphicBitmapData, new flash.geom.Rectangle(0, 0, width, height), new flash.geom.Point(0, 0));
  97. //set the bitmapData on the bitmap display object
  98. _bitmapDrawing.bitmapData = bitmapData;
  99. }
  100. //////////////////////////////////////////////////////////////////////////////////////////
  101. // Overriden Private fill control methods
  102. //////////////////////////////////////////////////////////////////////////////////////////
  103. /**
  104. * Do set the fill style on the Sprite
  105. * @param fillStyle
  106. */
  107. override public function setFillStyle(fillStyle:FillStyleValue):Void
  108. {
  109. switch(fillStyle)
  110. {
  111. //if there must be no fill style (probably only a stroke style)
  112. //start a transparent fill
  113. case none:
  114. _typedNativeElement.graphics.beginFill(0,0);
  115. //for a fill style with one color, use the native beginFill method
  116. case monochrome(colorStop):
  117. _typedNativeElement.graphics.beginFill(colorStop.color, toNativeAlpha(colorStop.alpha));
  118. //for a gradient fill, use the beginGradientFill native method
  119. case gradient(gradientStyle):
  120. _typedNativeElement.graphics.beginGradientFill(
  121. getGradientType(gradientStyle.gradientType),
  122. getGradientColors(gradientStyle.gradientStops),
  123. getGradientAlphas(gradientStyle.gradientStops),
  124. getGradientRatios(gradientStyle.gradientStops),
  125. getGradientBox(gradientStyle)
  126. );
  127. //for a bitmap fill, use the natvie beginBitmapFill method, using
  128. //an ImageHTMLElement as source for the bitmap data
  129. case bitmap(imageHTMLElement, repeat):
  130. _typedNativeElement.graphics.beginBitmapFill(getBitmapData(imageHTMLElement.nativeElement), new flash.geom.Matrix(), repeat);
  131. }
  132. }
  133. /**
  134. * Do set the lineStyle on the Sprite
  135. * @param lineStyle
  136. */
  137. override public function setLineStyle(lineStyle:LineStyleValue):Void
  138. {
  139. switch(lineStyle)
  140. {
  141. //if there must be no line (probably just a fill instead), do nothing
  142. case none:
  143. //if there must be a one-color line, use the native lineStyle method
  144. case monochrome(color, lineStyleData):
  145. //set the line style
  146. _typedNativeElement.graphics.lineStyle(
  147. lineStyleData.thickness,
  148. color.color,
  149. toNativeAlpha(color.alpha),
  150. true,
  151. LineScaleMode.NORMAL,
  152. toNativeCapStyle(lineStyleData.capStyle),
  153. toNativeJointStyle(lineStyleData.jointStyle),
  154. lineStyleData.miterLimit);
  155. //for a gradient line, use the native lineGradientStyle method
  156. case gradient(gradientStyle, lineStyleData):
  157. //set first the line style so that the line is visible
  158. _typedNativeElement.graphics.lineStyle(
  159. lineStyleData.thickness,
  160. 0,
  161. 1,
  162. true,
  163. LineScaleMode.NONE,
  164. toNativeCapStyle(lineStyleData.capStyle),
  165. toNativeJointStyle(lineStyleData.jointStyle),
  166. lineStyleData.miterLimit);
  167. _typedNativeElement.graphics.lineGradientStyle(
  168. getGradientType(gradientStyle.gradientType),
  169. getGradientColors(gradientStyle.gradientStops),
  170. getGradientAlphas(gradientStyle.gradientStops),
  171. getGradientRatios(gradientStyle.gradientStops),
  172. getGradientBox(gradientStyle)
  173. );
  174. //for a bitmap line style, use an ImageHTMLElement as the source
  175. //for the BitmapData. The line style must also be set before
  176. //setting the bitmap data on the line
  177. case bitmap(imageHTMLElement, lineStyleData, repeat):
  178. //set first the line style so that the line is visible
  179. _typedNativeElement.graphics.lineStyle(
  180. lineStyleData.thickness,
  181. 0,
  182. 1,
  183. true,
  184. LineScaleMode.NONE,
  185. toNativeCapStyle(lineStyleData.capStyle),
  186. toNativeJointStyle(lineStyleData.jointStyle),
  187. lineStyleData.miterLimit);
  188. //then set the bitmap data on it
  189. _typedNativeElement.graphics.lineBitmapStyle(getBitmapData(imageHTMLElement.nativeElement), new flash.geom.Matrix(), repeat);
  190. }
  191. }
  192. //////////////////////////////////////////////////////////////////////////////////////////
  193. // Overriden High level pixel manipulation method
  194. //////////////////////////////////////////////////////////////////////////////////////////
  195. /**
  196. * Draw a bitmap extracted from a NativeElement into the bitmap display object.
  197. */
  198. override public function drawImage(source:NativeElement, matrix:Matrix = null, sourceRect:RectangleData = null):Void
  199. {
  200. //init destination point and sourceRect if null
  201. if (matrix == null)
  202. {
  203. matrix = new Matrix();
  204. }
  205. if (sourceRect == null)
  206. {
  207. var width:Float = source.width;
  208. var height:Float = source.height;
  209. sourceRect = {
  210. x:0.0,
  211. y:0.0,
  212. width:width,
  213. height:height
  214. };
  215. }
  216. //get the ImageHTMLElement bitmap data and current bitmap data
  217. var sourceBitmapData:BitmapData = getBitmapData(source);
  218. var currentBitmapData:BitmapData = _bitmapDrawing.bitmapData;
  219. //convert the abstract rectangle and point into flash natives one
  220. var nativeSourceRect:flash.geom.Rectangle = new flash.geom.Rectangle(sourceRect.x, sourceRect.y, sourceRect.width, sourceRect.height);
  221. var matrixData:MatrixData = matrix.data;
  222. var nativeMatrix:flash.geom.Matrix = new flash.geom.Matrix(matrixData.a, matrixData.b, matrixData.c, matrixData.d, matrixData.e, matrixData.f);
  223. //draw the ImageHTMLElement bitmap data onto the current bitmap data
  224. currentBitmapData.draw(sourceBitmapData, nativeMatrix, null, null, nativeSourceRect);
  225. }
  226. //////////////////////////////////////////////////////////////////////////////////////////
  227. // Overriden low level drawing methods
  228. //////////////////////////////////////////////////////////////////////////////////////////
  229. /**
  230. * Use the native Flash lineTo method
  231. */
  232. override public function lineTo(x:Float, y:Float):Void
  233. {
  234. _typedNativeElement.graphics.lineTo(x, y);
  235. }
  236. /**
  237. * Use the native Flash moveTo method
  238. */
  239. override public function moveTo(x:Float, y:Float):Void
  240. {
  241. _typedNativeElement.graphics.moveTo(x, y);
  242. }
  243. /**
  244. * Use the native Flash curveTo method
  245. */
  246. override public function curveTo(controlX:Float, controlY:Float, x:Float, y:Float):Void
  247. {
  248. _typedNativeElement.graphics.curveTo(controlX, controlY, x, y);
  249. }
  250. //////////////////////////////////////////////////////////////////////////////////////////
  251. // Overriden utils conversion methods
  252. //////////////////////////////////////////////////////////////////////////////////////////
  253. /**
  254. * In Flash AVM2, alpha values range from 0 to 1
  255. */
  256. override private function toNativeAlpha(genericAlpha:Float):Dynamic
  257. {
  258. return genericAlpha;
  259. }
  260. /**
  261. * In Flash AVM2, ratio values range from 0 to 255
  262. */
  263. override private function toNativeRatio(genericRatio:Int):Dynamic
  264. {
  265. if (genericRatio == 0)
  266. {
  267. return 0;
  268. }
  269. return Math.round((255 / genericRatio) * 100);
  270. }
  271. /**
  272. * In Flash AVM2, the caps styles values are wrapped as a fake enum
  273. * @return a fake enum value (converted to string at compile time)
  274. */
  275. override private function toNativeCapStyle(genericCapStyle:CapsStyleValue):Dynamic
  276. {
  277. var capStyle:CapsStyle = CapsStyle.ROUND;
  278. switch(genericCapStyle)
  279. {
  280. case round:
  281. capStyle = CapsStyle.ROUND;
  282. case square:
  283. capStyle = CapsStyle.SQUARE;
  284. case none:
  285. capStyle = CapsStyle.NONE;
  286. }
  287. return capStyle;
  288. }
  289. /**
  290. * In Flash AVM2, the joint styles values are wrapped as a fake enum
  291. * @return a fake enum value (converted to string at compile time)
  292. */
  293. override private function toNativeJointStyle(genericJointStyle:JointStyleValue):Dynamic
  294. {
  295. var jointStyle:JointStyle = JointStyle.BEVEL;
  296. switch(genericJointStyle)
  297. {
  298. case miter:
  299. jointStyle = JointStyle.MITER;
  300. case round:
  301. jointStyle = JointStyle.ROUND;
  302. case bevel:
  303. jointStyle = JointStyle.BEVEL;
  304. }
  305. return jointStyle;
  306. }
  307. //////////////////////////////////////////////////////////////////////////////////////////
  308. // Utils methods
  309. //////////////////////////////////////////////////////////////////////////////////////////
  310. /**
  311. * Converts the generic type of Gradient (linear, radial) to a Flash
  312. * specific one
  313. * @return a strongly typed Flash gradient value
  314. */
  315. private function getGradientType(genericGradientType:GradientTypeValue):GradientType
  316. {
  317. var gradientType:GradientType = LINEAR;
  318. switch(genericGradientType)
  319. {
  320. case linear:
  321. gradientType = GradientType.LINEAR;
  322. case radial:
  323. gradientType = GradientType.RADIAL;
  324. }
  325. return gradientType;
  326. }
  327. /**
  328. * Get the bitmap data from a NativeElement
  329. * @return a bitmap data using the NativeElement sprite as it's source
  330. */
  331. private function getBitmapData(nativeElement:NativeElement):BitmapData
  332. {
  333. var nativeElementWidth:Int = Math.round(nativeElement.width);
  334. var nativeElementHeight:Int = Math.round(nativeElement.height);
  335. var bitmapData:BitmapData = new BitmapData(nativeElementWidth, nativeElementHeight, true, 0x00000000);
  336. bitmapData.draw(nativeElement);
  337. return bitmapData;
  338. }
  339. /**
  340. * Get the colors from the gradient stops data
  341. * @param gradientStops contains all the gradient data
  342. * @return an array of color
  343. */
  344. private function getGradientColors(gradientStops:Array<GradientStopData>):Array<Int>
  345. {
  346. var ret:Array<Int> = new Array<Int>();
  347. for (i in 0...gradientStops.length)
  348. {
  349. ret[i] = gradientStops[i].colorStop.color;
  350. }
  351. return ret;
  352. }
  353. /**
  354. * Get all the alphas of the color of gradient stops
  355. * @param gradientStops contains all the gradient data
  356. * @return an array of alpha (from 0 to 1)
  357. */
  358. private function getGradientAlphas(gradientStops:Array<GradientStopData>):Array<Float>
  359. {
  360. var ret:Array<Float> = new Array<Float>();
  361. for (i in 0...gradientStops.length)
  362. {
  363. ret[i] = toNativeAlpha(gradientStops[i].colorStop.alpha);
  364. }
  365. return ret;
  366. }
  367. /**
  368. * Get all the ratio of the colors of the gradient stop
  369. * @param gradientStops contains all the gradient data
  370. * @return an array of ratio (from 0 to 255)
  371. */
  372. private function getGradientRatios(gradientStops:Array<GradientStopData>):Array<Int>
  373. {
  374. var ret:Array<Int> = new Array<Int>();
  375. for (i in 0...gradientStops.length)
  376. {
  377. ret[i] = toNativeRatio(gradientStops[i].ratio);
  378. }
  379. return ret;
  380. }
  381. /**
  382. * create and return a gradient box corresponding to the size of the
  383. * whole HTMLElement
  384. */
  385. private function getGradientBox(gradientStyle:GradientStyleData):flash.geom.Matrix
  386. {
  387. var gradientBox:flash.geom.Matrix = new flash.geom.Matrix();
  388. gradientBox.createGradientBox(this.width, this.height, (gradientStyle.rotation) / 180 * Math.PI);
  389. return gradientBox;
  390. }
  391. //////////////////////////////////////////////////////////////////////////////////////////
  392. // OVERRIDEN SETTERS/GETTERS
  393. // update the bitmap surface when the width or height changes
  394. //////////////////////////////////////////////////////////////////////////////////////////
  395. override private function setWidth(value:Int):Int
  396. {
  397. super.setWidth(value);
  398. _bitmapDrawing = new Bitmap(new BitmapData(value, height, true, 0x00000000));
  399. this._nativeElement.addChild(_bitmapDrawing);
  400. return _width = value;
  401. }
  402. override private function setHeight(value:Int):Int
  403. {
  404. super.setHeight(value);
  405. _bitmapDrawing = new Bitmap(new BitmapData(width, value, true, 0x00000000));
  406. this._nativeElement.addChild(_bitmapDrawing);
  407. return _height = value;
  408. }
  409. }