CanvasRenderingContext2DWrapper.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <AK/FlyString.h>
  27. #include <AK/Function.h>
  28. #include <LibJS/Interpreter.h>
  29. #include <LibJS/Runtime/Error.h>
  30. #include <LibJS/Runtime/PrimitiveString.h>
  31. #include <LibJS/Runtime/Value.h>
  32. #include <LibWeb/Bindings/CanvasRenderingContext2DWrapper.h>
  33. #include <LibWeb/Bindings/HTMLImageElementWrapper.h>
  34. #include <LibWeb/DOM/CanvasRenderingContext2D.h>
  35. #include <LibWeb/DOM/HTMLImageElement.h>
  36. namespace Web {
  37. namespace Bindings {
  38. CanvasRenderingContext2DWrapper* wrap(JS::Heap& heap, CanvasRenderingContext2D& impl)
  39. {
  40. return static_cast<CanvasRenderingContext2DWrapper*>(wrap_impl(heap, impl));
  41. }
  42. CanvasRenderingContext2DWrapper::CanvasRenderingContext2DWrapper(CanvasRenderingContext2D& impl)
  43. : m_impl(impl)
  44. {
  45. put_native_property("fillStyle", fill_style_getter, fill_style_setter);
  46. put_native_function("fillRect", fill_rect, 4);
  47. put_native_function("scale", scale, 2);
  48. put_native_function("translate", translate, 2);
  49. put_native_property("strokeStyle", stroke_style_getter, stroke_style_setter);
  50. put_native_function("strokeRect", stroke_rect, 4);
  51. put_native_function("drawImage", draw_image, 3);
  52. put_native_function("beginPath", begin_path, 0);
  53. put_native_function("closePath", close_path, 0);
  54. put_native_function("stroke", stroke, 0);
  55. put_native_function("moveTo", move_to, 0);
  56. put_native_function("lineTo", line_to, 0);
  57. put_native_property("lineWidth", line_width_getter, line_width_setter);
  58. }
  59. CanvasRenderingContext2DWrapper::~CanvasRenderingContext2DWrapper()
  60. {
  61. }
  62. static CanvasRenderingContext2D* impl_from(JS::Interpreter& interpreter)
  63. {
  64. auto* this_object = interpreter.this_value().to_object(interpreter.heap());
  65. if (!this_object)
  66. return nullptr;
  67. // FIXME: Verify that it's a CanvasRenderingContext2DWrapper somehow!
  68. return &static_cast<CanvasRenderingContext2DWrapper*>(this_object)->impl();
  69. }
  70. JS::Value CanvasRenderingContext2DWrapper::fill_rect(JS::Interpreter& interpreter)
  71. {
  72. auto* impl = impl_from(interpreter);
  73. if (!impl)
  74. return {};
  75. auto& arguments = interpreter.call_frame().arguments;
  76. if (arguments.size() >= 4)
  77. impl->fill_rect(arguments[0].to_double(), arguments[1].to_double(), arguments[2].to_double(), arguments[3].to_double());
  78. return JS::js_undefined();
  79. }
  80. JS::Value CanvasRenderingContext2DWrapper::stroke_rect(JS::Interpreter& interpreter)
  81. {
  82. auto* impl = impl_from(interpreter);
  83. if (!impl)
  84. return {};
  85. auto& arguments = interpreter.call_frame().arguments;
  86. if (arguments.size() >= 4)
  87. impl->stroke_rect(arguments[0].to_double(), arguments[1].to_double(), arguments[2].to_double(), arguments[3].to_double());
  88. return JS::js_undefined();
  89. }
  90. JS::Value CanvasRenderingContext2DWrapper::draw_image(JS::Interpreter& interpreter)
  91. {
  92. auto* impl = impl_from(interpreter);
  93. if (!impl)
  94. return {};
  95. auto& arguments = interpreter.call_frame().arguments;
  96. if (arguments.size() < 3)
  97. return interpreter.throw_exception<JS::TypeError>("drawImage() needs more arguments");
  98. auto* image_argument = arguments[0].to_object(interpreter.heap());
  99. if (!image_argument)
  100. return {};
  101. if (StringView(image_argument->class_name()) != "HTMLImageElementWrapper")
  102. return interpreter.throw_exception<JS::TypeError>(String::format("Image is not an HTMLImageElement, it's an %s", image_argument->class_name()));
  103. auto x = arguments[1].to_double();
  104. auto y = arguments[2].to_double();
  105. impl->draw_image(static_cast<const HTMLImageElementWrapper&>(*image_argument).node(), x, y);
  106. return JS::js_undefined();
  107. }
  108. JS::Value CanvasRenderingContext2DWrapper::scale(JS::Interpreter& interpreter)
  109. {
  110. auto* impl = impl_from(interpreter);
  111. if (!impl)
  112. return {};
  113. auto& arguments = interpreter.call_frame().arguments;
  114. if (arguments.size() >= 2)
  115. impl->scale(arguments[0].to_double(), arguments[1].to_double());
  116. return JS::js_undefined();
  117. }
  118. JS::Value CanvasRenderingContext2DWrapper::translate(JS::Interpreter& interpreter)
  119. {
  120. auto* impl = impl_from(interpreter);
  121. if (!impl)
  122. return {};
  123. auto& arguments = interpreter.call_frame().arguments;
  124. if (arguments.size() >= 2)
  125. impl->translate(arguments[0].to_double(), arguments[1].to_double());
  126. return JS::js_undefined();
  127. }
  128. JS::Value CanvasRenderingContext2DWrapper::fill_style_getter(JS::Interpreter& interpreter)
  129. {
  130. auto* impl = impl_from(interpreter);
  131. if (!impl)
  132. return {};
  133. return JS::js_string(interpreter, impl->fill_style());
  134. }
  135. void CanvasRenderingContext2DWrapper::fill_style_setter(JS::Interpreter& interpreter, JS::Value value)
  136. {
  137. if (auto* impl = impl_from(interpreter))
  138. impl->set_fill_style(value.to_string());
  139. }
  140. JS::Value CanvasRenderingContext2DWrapper::stroke_style_getter(JS::Interpreter& interpreter)
  141. {
  142. auto* impl = impl_from(interpreter);
  143. if (!impl)
  144. return {};
  145. return JS::js_string(interpreter, impl->stroke_style());
  146. }
  147. void CanvasRenderingContext2DWrapper::stroke_style_setter(JS::Interpreter& interpreter, JS::Value value)
  148. {
  149. if (auto* impl = impl_from(interpreter))
  150. impl->set_stroke_style(value.to_string());
  151. }
  152. JS::Value CanvasRenderingContext2DWrapper::line_width_getter(JS::Interpreter& interpreter)
  153. {
  154. auto* impl = impl_from(interpreter);
  155. if (!impl)
  156. return {};
  157. return JS::Value(impl->line_width());
  158. }
  159. void CanvasRenderingContext2DWrapper::line_width_setter(JS::Interpreter& interpreter, JS::Value value)
  160. {
  161. if (auto* impl = impl_from(interpreter))
  162. impl->set_line_width(value.to_double());
  163. }
  164. JS::Value CanvasRenderingContext2DWrapper::begin_path(JS::Interpreter& interpreter)
  165. {
  166. auto* impl = impl_from(interpreter);
  167. if (!impl)
  168. return {};
  169. impl->begin_path();
  170. return JS::js_undefined();
  171. }
  172. JS::Value CanvasRenderingContext2DWrapper::close_path(JS::Interpreter& interpreter)
  173. {
  174. auto* impl = impl_from(interpreter);
  175. if (!impl)
  176. return {};
  177. impl->close_path();
  178. return JS::js_undefined();
  179. }
  180. JS::Value CanvasRenderingContext2DWrapper::stroke(JS::Interpreter& interpreter)
  181. {
  182. auto* impl = impl_from(interpreter);
  183. if (!impl)
  184. return {};
  185. impl->stroke();
  186. return JS::js_undefined();
  187. }
  188. JS::Value CanvasRenderingContext2DWrapper::move_to(JS::Interpreter& interpreter)
  189. {
  190. auto* impl = impl_from(interpreter);
  191. if (!impl)
  192. return {};
  193. double x = interpreter.argument(0).to_double();
  194. double y = interpreter.argument(1).to_double();
  195. impl->move_to(x, y);
  196. return JS::js_undefined();
  197. }
  198. JS::Value CanvasRenderingContext2DWrapper::line_to(JS::Interpreter& interpreter)
  199. {
  200. auto* impl = impl_from(interpreter);
  201. if (!impl)
  202. return {};
  203. double x = interpreter.argument(0).to_double();
  204. double y = interpreter.argument(1).to_double();
  205. impl->line_to(x, y);
  206. return JS::js_undefined();
  207. }
  208. }
  209. }