CanvasPattern.cc 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Copyright (c) 2010 LearnBoost <tj@learnboost.com>
  2. #include "CanvasPattern.h"
  3. #include "Canvas.h"
  4. #include "Image.h"
  5. using namespace v8;
  6. const cairo_user_data_key_t *pattern_repeat_key;
  7. Nan::Persistent<FunctionTemplate> Pattern::constructor;
  8. Nan::Persistent<Function> Pattern::_DOMMatrix;
  9. /*
  10. * Initialize CanvasPattern.
  11. */
  12. void
  13. Pattern::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
  14. Nan::HandleScope scope;
  15. // Constructor
  16. Local<FunctionTemplate> ctor = Nan::New<FunctionTemplate>(Pattern::New);
  17. constructor.Reset(ctor);
  18. ctor->InstanceTemplate()->SetInternalFieldCount(1);
  19. ctor->SetClassName(Nan::New("CanvasPattern").ToLocalChecked());
  20. Nan::SetPrototypeMethod(ctor, "setTransform", SetTransform);
  21. // Prototype
  22. Local<Context> ctx = Nan::GetCurrentContext();
  23. Nan::Set(target, Nan::New("CanvasPattern").ToLocalChecked(), ctor->GetFunction(ctx).ToLocalChecked());
  24. Nan::Set(target, Nan::New("CanvasPatternInit").ToLocalChecked(), Nan::New<Function>(SaveExternalModules));
  25. }
  26. /*
  27. * Save some external modules as private references.
  28. */
  29. NAN_METHOD(Pattern::SaveExternalModules) {
  30. _DOMMatrix.Reset(Nan::To<Function>(info[0]).ToLocalChecked());
  31. }
  32. /*
  33. * Initialize a new CanvasPattern.
  34. */
  35. NAN_METHOD(Pattern::New) {
  36. if (!info.IsConstructCall()) {
  37. return Nan::ThrowTypeError("Class constructors cannot be invoked without 'new'");
  38. }
  39. cairo_surface_t *surface;
  40. Local<Object> obj = Nan::To<Object>(info[0]).ToLocalChecked();
  41. // Image
  42. if (Nan::New(Image::constructor)->HasInstance(obj)) {
  43. Image *img = Nan::ObjectWrap::Unwrap<Image>(obj);
  44. if (!img->isComplete()) {
  45. return Nan::ThrowError("Image given has not completed loading");
  46. }
  47. surface = img->surface();
  48. // Canvas
  49. } else if (Nan::New(Canvas::constructor)->HasInstance(obj)) {
  50. Canvas *canvas = Nan::ObjectWrap::Unwrap<Canvas>(obj);
  51. surface = canvas->surface();
  52. // Invalid
  53. } else {
  54. return Nan::ThrowTypeError("Image or Canvas expected");
  55. }
  56. repeat_type_t repeat = REPEAT;
  57. if (0 == strcmp("no-repeat", *Nan::Utf8String(info[1]))) {
  58. repeat = NO_REPEAT;
  59. } else if (0 == strcmp("repeat-x", *Nan::Utf8String(info[1]))) {
  60. repeat = REPEAT_X;
  61. } else if (0 == strcmp("repeat-y", *Nan::Utf8String(info[1]))) {
  62. repeat = REPEAT_Y;
  63. }
  64. Pattern *pattern = new Pattern(surface, repeat);
  65. pattern->Wrap(info.This());
  66. info.GetReturnValue().Set(info.This());
  67. }
  68. /*
  69. * Set the pattern-space to user-space transform.
  70. */
  71. NAN_METHOD(Pattern::SetTransform) {
  72. Pattern *pattern = Nan::ObjectWrap::Unwrap<Pattern>(info.This());
  73. Local<Context> ctx = Nan::GetCurrentContext();
  74. Local<Object> mat = Nan::To<Object>(info[0]).ToLocalChecked();
  75. #if NODE_MAJOR_VERSION >= 8
  76. if (!mat->InstanceOf(ctx, _DOMMatrix.Get(Isolate::GetCurrent())).ToChecked()) {
  77. return Nan::ThrowTypeError("Expected DOMMatrix");
  78. }
  79. #endif
  80. cairo_matrix_t matrix;
  81. cairo_matrix_init(&matrix,
  82. Nan::To<double>(Nan::Get(mat, Nan::New("a").ToLocalChecked()).ToLocalChecked()).FromMaybe(1),
  83. Nan::To<double>(Nan::Get(mat, Nan::New("b").ToLocalChecked()).ToLocalChecked()).FromMaybe(0),
  84. Nan::To<double>(Nan::Get(mat, Nan::New("c").ToLocalChecked()).ToLocalChecked()).FromMaybe(0),
  85. Nan::To<double>(Nan::Get(mat, Nan::New("d").ToLocalChecked()).ToLocalChecked()).FromMaybe(1),
  86. Nan::To<double>(Nan::Get(mat, Nan::New("e").ToLocalChecked()).ToLocalChecked()).FromMaybe(0),
  87. Nan::To<double>(Nan::Get(mat, Nan::New("f").ToLocalChecked()).ToLocalChecked()).FromMaybe(0)
  88. );
  89. cairo_matrix_invert(&matrix);
  90. cairo_pattern_set_matrix(pattern->_pattern, &matrix);
  91. }
  92. /*
  93. * Initialize pattern.
  94. */
  95. Pattern::Pattern(cairo_surface_t *surface, repeat_type_t repeat) {
  96. _pattern = cairo_pattern_create_for_surface(surface);
  97. _repeat = repeat;
  98. cairo_pattern_set_user_data(_pattern, pattern_repeat_key, &_repeat, NULL);
  99. }
  100. repeat_type_t Pattern::get_repeat_type_for_cairo_pattern(cairo_pattern_t *pattern) {
  101. void *ud = cairo_pattern_get_user_data(pattern, pattern_repeat_key);
  102. return *reinterpret_cast<repeat_type_t*>(ud);
  103. }
  104. /*
  105. * Destroy the pattern.
  106. */
  107. Pattern::~Pattern() {
  108. cairo_pattern_destroy(_pattern);
  109. }