# Global Metrics

path: .metrics.cyclomatic.sum
old: 4.0
new: 67.0
path: .metrics.cyclomatic.average
old: 1.0
new: 2.2333333333333334
path: .metrics.nexits.sum
old: 0.0
new: 28.0
path: .metrics.nexits.average
old: null
new: 1.037037037037037
path: .metrics.cognitive.sum
old: 0.0
new: 39.0
path: .metrics.cognitive.average
old: null
new: 1.4444444444444444
path: .metrics.nom.total
old: 0.0
new: 27.0
path: .metrics.nom.functions
old: 0.0
new: 27.0
path: .metrics.halstead.N1
old: 110.0
new: 759.0
path: .metrics.halstead.length
old: 205.0
new: 1247.0
path: .metrics.halstead.time
old: 676.6459048155574
new: 18165.03222511953
path: .metrics.halstead.effort
old: 12179.626286680032
new: 326970.5800521515
path: .metrics.halstead.bugs
old: 0.17645530535138337
new: 1.5820414711747477
path: .metrics.halstead.level
old: 0.10350877192982456
new: 0.029751062537947785
path: .metrics.halstead.estimated_program_length
old: 390.0954899210025
new: 1620.8650920049945
path: .metrics.halstead.n1
old: 12.0
new: 27.0
path: .metrics.halstead.purity_ratio
old: 1.902904828882939
new: 1.299811621495585
path: .metrics.halstead.N2
old: 95.0
new: 488.0
path: .metrics.halstead.vocabulary
old: 71.0
new: 223.0
path: .metrics.halstead.volume
old: 1260.6981594984595
new: 9727.72217520062
path: .metrics.halstead.n2
old: 59.0
new: 196.0
path: .metrics.halstead.difficulty
old: 9.66101694915254
new: 33.61224489795919
path: .metrics.mi.mi_original
old: 54.6072442124612
new: 12.665899928768908
path: .metrics.mi.mi_visual_studio
old: 31.934060942959768
new: 7.4069590226718764
path: .metrics.mi.mi_sei
old: 43.13064795538851
new: -33.09065169310504
path: .metrics.loc.cloc
old: 44.0
new: 19.0
path: .metrics.loc.ploc
old: 53.0
new: 278.0
path: .metrics.loc.blank
old: 29.0
new: 59.0
path: .metrics.loc.lloc
old: 0.0
new: 111.0
path: .metrics.loc.sloc
old: 126.0
new: 356.0
path: .metrics.nargs.average
old: null
new: 0.6666666666666666
path: .metrics.nargs.sum
old: 0.0
new: 18.0

# Spaces Data

## Minimal test - lines (25, 356)

path: .spaces[0].metrics.nexits.sum
old: 0.0
new: 28.0
path: .spaces[0].metrics.nexits.average
old: null
new: 1.037037037037037
path: .spaces[0].metrics.nom.total
old: 0.0
new: 27.0
path: .spaces[0].metrics.nom.functions
old: 0.0
new: 27.0
path: .spaces[0].metrics.cognitive.average
old: null
new: 1.4444444444444444
path: .spaces[0].metrics.cognitive.sum
old: 0.0
new: 39.0
path: .spaces[0].metrics.cyclomatic.average
old: 1.0
new: 2.2758620689655173
path: .spaces[0].metrics.cyclomatic.sum
old: 1.0
new: 66.0
path: .spaces[0].metrics.loc.blank
old: 0.0
new: 56.0
path: .spaces[0].metrics.loc.ploc
old: 1.0
new: 262.0
path: .spaces[0].metrics.loc.cloc
old: 0.0
new: 14.0
path: .spaces[0].metrics.loc.sloc
old: 1.0
new: 332.0
path: .spaces[0].metrics.loc.lloc
old: 0.0
new: 111.0
path: .spaces[0].metrics.halstead.N1
old: 0.0
new: 759.0
path: .spaces[0].metrics.halstead.volume
old: 0.0
new: 9486.941732749823
path: .spaces[0].metrics.halstead.level
old: null
new: 0.02834547020593532
path: .spaces[0].metrics.halstead.bugs
old: 0.0
new: 1.606844277071659
path: .spaces[0].metrics.halstead.N2
old: 1.0
new: 473.0
path: .spaces[0].metrics.halstead.effort
old: 0.0
new: 334689.8698037238
path: .spaces[0].metrics.halstead.n1
old: 0.0
new: 27.0
path: .spaces[0].metrics.halstead.purity_ratio
old: null
new: 1.2060503799679172
path: .spaces[0].metrics.halstead.time
old: 0.0
new: 18593.88165576243
path: .spaces[0].metrics.halstead.length
old: 1.0
new: 1232.0
path: .spaces[0].metrics.halstead.estimated_program_length
old: null
new: 1485.854068120474
path: .spaces[0].metrics.halstead.vocabulary
old: 1.0
new: 208.0
path: .spaces[0].metrics.halstead.difficulty
old: 0.0
new: 35.27900552486188
path: .spaces[0].metrics.halstead.n2
old: 1.0
new: 181.0
path: .spaces[0].metrics.nargs.sum
old: 0.0
new: 18.0
path: .spaces[0].metrics.nargs.average
old: null
new: 0.6666666666666666
path: .spaces[0].metrics.mi.mi_original
old: null
new: 14.156921300164484
path: .spaces[0].metrics.mi.mi_sei
old: null
new: -32.917214194979785
path: .spaces[0].metrics.mi.mi_visual_studio
old: null
new: 8.278901345125428

### Code

    namespace mozilla {
    namespace widget {

    using namespace mozilla::gfx;
    using namespace mozilla;

    /* static */
    RefPtr CompositorWidget::CreateLocal(
        const CompositorWidgetInitData& aInitData,
        const layers::CompositorOptions& aOptions, nsIWidget* aWidget) {
      if (aInitData.type() ==
          CompositorWidgetInitData::THeadlessCompositorWidgetInitData) {
        return new HeadlessCompositorWidget(
            aInitData.get_HeadlessCompositorWidgetInitData(), aOptions,
            static_cast(aWidget));
      } else {
        return new InProcessWinCompositorWidget(
            aInitData.get_WinCompositorWidgetInitData(), aOptions,
            static_cast(aWidget));
      }
    }

    InProcessWinCompositorWidget::InProcessWinCompositorWidget(
        const WinCompositorWidgetInitData& aInitData,
        const layers::CompositorOptions& aOptions, nsWindow* aWindow)
        : WinCompositorWidget(aInitData, aOptions),
          mWindow(aWindow),
          mWnd(reinterpret_cast(aInitData.hWnd())),
          mTransparentSurfaceLock("mTransparentSurfaceLock"),
          mTransparencyMode(aInitData.transparencyMode()),
          mMemoryDC(nullptr),
          mCompositeDC(nullptr),
          mLockedBackBufferData(nullptr) {
      MOZ_ASSERT(mWindow);
      MOZ_ASSERT(mWnd && ::IsWindow(mWnd));

      // mNotDeferEndRemoteDrawing is set on the main thread during init,
      // but is only accessed after on the compositor thread.
      mNotDeferEndRemoteDrawing =
          StaticPrefs::layers_offmainthreadcomposition_frame_rate() == 0 ||
          gfxPlatform::IsInLayoutAsapMode() || gfxPlatform::ForceSoftwareVsync();
    }

    void InProcessWinCompositorWidget::OnDestroyWindow() {
      EnterPresentLock();
      MutexAutoLock lock(mTransparentSurfaceLock);
      mTransparentSurface = nullptr;
      mMemoryDC = nullptr;
      LeavePresentLock();
    }

    bool InProcessWinCompositorWidget::OnWindowResize(
        const LayoutDeviceIntSize& aSize) {
      return true;
    }

    void InProcessWinCompositorWidget::OnWindowModeChange(nsSizeMode aSizeMode) {}

    bool InProcessWinCompositorWidget::PreRender(WidgetRenderingContext* aContext) {
      // This can block waiting for WM_SETTEXT to finish
      // Using PreRender is unnecessarily pessimistic because
      // we technically only need to block during the present call
      // not all of compositor rendering
      mPresentLock.Enter();
      return true;
    }

    void InProcessWinCompositorWidget::PostRender(
        WidgetRenderingContext* aContext) {
      mPresentLock.Leave();
    }

    LayoutDeviceIntSize InProcessWinCompositorWidget::GetClientSize() {
      RECT r;
      if (!::GetClientRect(mWnd, &r)) {
        return LayoutDeviceIntSize();
      }
      return LayoutDeviceIntSize(r.right - r.left, r.bottom - r.top);
    }

    already_AddRefed
    InProcessWinCompositorWidget::StartRemoteDrawing() {
      MutexAutoLock lock(mTransparentSurfaceLock);

      MOZ_ASSERT(!mCompositeDC);

      RefPtr surf;
      if (mTransparencyMode == eTransparencyTransparent) {
        surf = EnsureTransparentSurface();
      }

      // Must call this after EnsureTransparentSurface(), since it could update
      // the DC.
      HDC dc = GetWindowSurface();
      if (!surf) {
        if (!dc) {
          return nullptr;
        }
        uint32_t flags = (mTransparencyMode == eTransparencyOpaque)
                             ? 0
                             : gfxWindowsSurface::FLAG_IS_TRANSPARENT;
        surf = new gfxWindowsSurface(dc, flags);
      }

      IntSize size = surf->GetSize();
      if (size.width <= 0 || size.height <= 0) {
        if (dc) {
          FreeWindowSurface(dc);
        }
        return nullptr;
      }

      RefPtr dt =
          mozilla::gfx::Factory::CreateDrawTargetForCairoSurface(
              surf->CairoSurface(), size);
      if (dt) {
        mCompositeDC = dc;
      } else {
        FreeWindowSurface(dc);
      }

      return dt.forget();
    }

    void InProcessWinCompositorWidget::EndRemoteDrawing() {
      MOZ_ASSERT(!mLockedBackBufferData);

      if (mTransparencyMode == eTransparencyTransparent) {
        MOZ_ASSERT(mTransparentSurface);
        RedrawTransparentWindow();
      }
      if (mCompositeDC) {
        FreeWindowSurface(mCompositeDC);
      }
      mCompositeDC = nullptr;
    }

    bool InProcessWinCompositorWidget::NeedsToDeferEndRemoteDrawing() {
      if (mNotDeferEndRemoteDrawing) {
        return false;
      }

      IDirectDraw7* ddraw = DeviceManagerDx::Get()->GetDirectDraw();
      if (!ddraw) {
        return false;
      }

      DWORD scanLine = 0;
      int height = ::GetSystemMetrics(SM_CYSCREEN);
      HRESULT ret = ddraw->GetScanLine(&scanLine);
      if (ret == DDERR_VERTICALBLANKINPROGRESS) {
        scanLine = 0;
      } else if (ret != DD_OK) {
        return false;
      }

      // Check if there is a risk of tearing with GDI.
      if (static_cast(scanLine) > height / 2) {
        // No need to defer.
        return false;
      }

      return true;
    }

    already_AddRefed
    InProcessWinCompositorWidget::GetBackBufferDrawTarget(
        gfx::DrawTarget* aScreenTarget, const gfx::IntRect& aRect,
        bool* aOutIsCleared) {
      MOZ_ASSERT(!mLockedBackBufferData);

      RefPtr target = CompositorWidget::GetBackBufferDrawTarget(
          aScreenTarget, aRect, aOutIsCleared);
      if (!target) {
        return nullptr;
      }

      MOZ_ASSERT(target->GetBackendType() == BackendType::CAIRO);

      uint8_t* destData;
      IntSize destSize;
      int32_t destStride;
      SurfaceFormat destFormat;
      if (!target->LockBits(&destData, &destSize, &destStride, &destFormat)) {
        // LockBits is not supported. Use original DrawTarget.
        return target.forget();
      }

      RefPtr dataTarget = Factory::CreateDrawTargetForData(
          BackendType::CAIRO, destData, destSize, destStride, destFormat);
      mLockedBackBufferData = destData;

      return dataTarget.forget();
    }

    already_AddRefed
    InProcessWinCompositorWidget::EndBackBufferDrawing() {
      if (mLockedBackBufferData) {
        MOZ_ASSERT(mLastBackBuffer);
        mLastBackBuffer->ReleaseBits(mLockedBackBufferData);
        mLockedBackBufferData = nullptr;
      }
      return CompositorWidget::EndBackBufferDrawing();
    }

    bool InProcessWinCompositorWidget::InitCompositor(
        layers::Compositor* aCompositor) {
      if (aCompositor->GetBackendType() == layers::LayersBackend::LAYERS_BASIC) {
        DeviceManagerDx::Get()->InitializeDirectDraw();
      }
      return true;
    }

    void InProcessWinCompositorWidget::EnterPresentLock() { mPresentLock.Enter(); }

    void InProcessWinCompositorWidget::LeavePresentLock() { mPresentLock.Leave(); }

    RefPtr InProcessWinCompositorWidget::EnsureTransparentSurface() {
      mTransparentSurfaceLock.AssertCurrentThreadOwns();
      MOZ_ASSERT(mTransparencyMode == eTransparencyTransparent);

      IntSize size = GetClientSize().ToUnknownSize();
      if (!mTransparentSurface || mTransparentSurface->GetSize() != size) {
        mTransparentSurface = nullptr;
        mMemoryDC = nullptr;
        CreateTransparentSurface(size);
      }

      RefPtr surface = mTransparentSurface;
      return surface.forget();
    }

    void InProcessWinCompositorWidget::CreateTransparentSurface(
        const gfx::IntSize& aSize) {
      mTransparentSurfaceLock.AssertCurrentThreadOwns();
      MOZ_ASSERT(!mTransparentSurface && !mMemoryDC);
      RefPtr surface =
          new gfxWindowsSurface(aSize, SurfaceFormat::A8R8G8B8_UINT32);
      mTransparentSurface = surface;
      mMemoryDC = surface->GetDC();
    }

    void InProcessWinCompositorWidget::UpdateTransparency(
        nsTransparencyMode aMode) {
      EnterPresentLock();
      MutexAutoLock lock(mTransparentSurfaceLock);
      if (mTransparencyMode == aMode) {
        return;
      }

      mTransparencyMode = aMode;
      mTransparentSurface = nullptr;
      mMemoryDC = nullptr;

      if (mTransparencyMode == eTransparencyTransparent) {
        EnsureTransparentSurface();
      }
      LeavePresentLock();
    }

    bool InProcessWinCompositorWidget::HasGlass() const {
      MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread() ||
                 wr::RenderThread::IsInRenderThread());

      nsTransparencyMode transparencyMode = mTransparencyMode;
      return transparencyMode == eTransparencyGlass ||
             transparencyMode == eTransparencyBorderlessGlass;
    }

    void InProcessWinCompositorWidget::ClearTransparentWindow() {
      EnterPresentLock();
      MutexAutoLock lock(mTransparentSurfaceLock);
      if (!mTransparentSurface) {
        return;
      }

      EnsureTransparentSurface();

      IntSize size = mTransparentSurface->GetSize();
      if (!size.IsEmpty()) {
        RefPtr drawTarget =
            gfxPlatform::CreateDrawTargetForSurface(mTransparentSurface, size);
        if (!drawTarget) {
          return;
        }
        drawTarget->ClearRect(Rect(0, 0, size.width, size.height));
        RedrawTransparentWindow();
      }
      LeavePresentLock();
    }

    bool InProcessWinCompositorWidget::RedrawTransparentWindow() {
      MOZ_ASSERT(mTransparencyMode == eTransparencyTransparent);

      LayoutDeviceIntSize size = GetClientSize();

      ::GdiFlush();

      BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
      SIZE winSize = {size.width, size.height};
      POINT srcPos = {0, 0};
      HWND hWnd = WinUtils::GetTopLevelHWND(mWnd, true);
      RECT winRect;
      ::GetWindowRect(hWnd, &winRect);

      // perform the alpha blend
      return !!::UpdateLayeredWindow(hWnd, nullptr, (POINT*)&winRect, &winSize,
                                     mMemoryDC, &srcPos, 0, &bf, ULW_ALPHA);
    }

    HDC InProcessWinCompositorWidget::GetWindowSurface() {
      return eTransparencyTransparent == mTransparencyMode ? mMemoryDC
                                                           : ::GetDC(mWnd);
    }

    void InProcessWinCompositorWidget::FreeWindowSurface(HDC dc) {
      if (eTransparencyTransparent != mTransparencyMode) ::ReleaseDC(mWnd, dc);
    }

    bool InProcessWinCompositorWidget::IsHidden() const { return ::IsIconic(mWnd); }

    nsIWidget* InProcessWinCompositorWidget::RealWidget() { return mWindow; }

    void InProcessWinCompositorWidget::ObserveVsync(VsyncObserver* aObserver) {
      if (RefPtr cvd =
              mWindow->GetCompositorVsyncDispatcher()) {
        cvd->SetCompositorVsyncObserver(aObserver);
      }
    }

    }  // namespace widget
    }  // namespace mozilla