PrintTarget.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. * This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "PrintTarget.h"
  6. #include "cairo.h"
  7. #include "mozilla/gfx/2D.h"
  8. #include "mozilla/gfx/Logging.h"
  9. namespace mozilla {
  10. namespace gfx {
  11. PrintTarget::PrintTarget(cairo_surface_t* aCairoSurface, const IntSize& aSize)
  12. : mCairoSurface(aCairoSurface)
  13. , mSize(aSize)
  14. , mIsFinished(false)
  15. #ifdef DEBUG
  16. , mHasActivePage(false)
  17. #endif
  18. {
  19. #if 0
  20. // aCairoSurface is null when our PrintTargetThebes subclass's ctor calls us.
  21. // Once PrintTargetThebes is removed, enable this assertion.
  22. MOZ_ASSERT(aCairoSurface && !cairo_surface_status(aCairoSurface),
  23. "CreateOrNull factory methods should not call us without a "
  24. "valid cairo_surface_t*");
  25. #endif
  26. // CreateOrNull factory methods hand over ownership of aCairoSurface,
  27. // so we don't call cairo_surface_reference(aSurface) here.
  28. // This code was copied from gfxASurface::Init:
  29. #ifdef MOZ_TREE_CAIRO
  30. if (mCairoSurface &&
  31. cairo_surface_get_content(mCairoSurface) != CAIRO_CONTENT_COLOR) {
  32. cairo_surface_set_subpixel_antialiasing(mCairoSurface,
  33. CAIRO_SUBPIXEL_ANTIALIASING_DISABLED);
  34. }
  35. #endif
  36. }
  37. PrintTarget::~PrintTarget()
  38. {
  39. // null surfaces are allowed here
  40. cairo_surface_destroy(mCairoSurface);
  41. mCairoSurface = nullptr;
  42. }
  43. already_AddRefed<DrawTarget>
  44. PrintTarget::MakeDrawTarget(const IntSize& aSize,
  45. DrawEventRecorder* aRecorder)
  46. {
  47. MOZ_ASSERT(mCairoSurface,
  48. "We shouldn't have been constructed without a cairo surface");
  49. // This should not be called outside of BeginPage()/EndPage() calls since
  50. // some backends can only provide a valid DrawTarget at that time.
  51. MOZ_ASSERT(mHasActivePage, "We can't guarantee a valid DrawTarget");
  52. if (cairo_surface_status(mCairoSurface)) {
  53. return nullptr;
  54. }
  55. // Note than aSize may not be the same as mSize (the size of mCairoSurface).
  56. // See the comments in our header. If the sizes are different a clip will
  57. // be applied to mCairoSurface.
  58. RefPtr<DrawTarget> dt =
  59. Factory::CreateDrawTargetForCairoSurface(mCairoSurface, aSize);
  60. if (!dt || !dt->IsValid()) {
  61. return nullptr;
  62. }
  63. if (aRecorder) {
  64. dt = CreateRecordingDrawTarget(aRecorder, dt);
  65. if (!dt || !dt->IsValid()) {
  66. return nullptr;
  67. }
  68. }
  69. return dt.forget();
  70. }
  71. already_AddRefed<DrawTarget>
  72. PrintTarget::GetReferenceDrawTarget(DrawEventRecorder* aRecorder)
  73. {
  74. if (!mRefDT) {
  75. IntSize size(1, 1);
  76. cairo_surface_t* surface =
  77. cairo_surface_create_similar(mCairoSurface,
  78. cairo_surface_get_content(mCairoSurface),
  79. size.width, size.height);
  80. if (cairo_surface_status(surface)) {
  81. return nullptr;
  82. }
  83. RefPtr<DrawTarget> dt =
  84. Factory::CreateDrawTargetForCairoSurface(surface, size);
  85. // The DT addrefs the surface, so we need drop our own reference to it:
  86. cairo_surface_destroy(surface);
  87. if (!dt || !dt->IsValid()) {
  88. return nullptr;
  89. }
  90. if (aRecorder) {
  91. dt = CreateRecordingDrawTarget(aRecorder, dt);
  92. if (!dt || !dt->IsValid()) {
  93. return nullptr;
  94. }
  95. }
  96. mRefDT = dt.forget();
  97. }
  98. return do_AddRef(mRefDT);
  99. }
  100. already_AddRefed<DrawTarget>
  101. PrintTarget::CreateRecordingDrawTarget(DrawEventRecorder* aRecorder,
  102. DrawTarget* aDrawTarget)
  103. {
  104. MOZ_ASSERT(aRecorder);
  105. MOZ_ASSERT(aDrawTarget);
  106. RefPtr<DrawTarget> dt;
  107. if (aRecorder) {
  108. // It doesn't really matter what we pass as the DrawTarget here.
  109. dt = gfx::Factory::CreateRecordingDrawTarget(aRecorder, aDrawTarget);
  110. }
  111. if (!dt || !dt->IsValid()) {
  112. gfxCriticalNote
  113. << "Failed to create a recording DrawTarget for PrintTarget";
  114. return nullptr;
  115. }
  116. return dt.forget();
  117. }
  118. void
  119. PrintTarget::Finish()
  120. {
  121. if (mIsFinished) {
  122. return;
  123. }
  124. mIsFinished = true;
  125. // null surfaces are allowed here
  126. cairo_surface_finish(mCairoSurface);
  127. }
  128. } // namespace gfx
  129. } // namespace mozilla