PageRenderTime 57ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/src/cocktail/port/flash_player/DrawingManager.hx

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