// Copyright 2015 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "JBig2_HtrdProc.h"

#include "../../../include/fxcrt/fx_basic.h"
#include "JBig2_GsidProc.h"
#include "third_party/base/nonstd_unique_ptr.h"

CJBig2_Image* CJBig2_HTRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder,
                                            JBig2ArithCtx* gbContext,
                                            IFX_Pause* pPause) {
  FX_DWORD ng, mg;
  int32_t x, y;
  FX_DWORD HBPP;
  FX_DWORD* GI;
  nonstd::unique_ptr<CJBig2_Image> HSKIP;
  nonstd::unique_ptr<CJBig2_Image> HTREG(new CJBig2_Image(HBW, HBH));
  HTREG->fill(HDEFPIXEL);
  if (HENABLESKIP == 1) {
    HSKIP.reset(new CJBig2_Image(HGW, HGH));
    for (mg = 0; mg < HGH; mg++) {
      for (ng = 0; ng < HGW; ng++) {
        x = (HGX + mg * HRY + ng * HRX) >> 8;
        y = (HGY + mg * HRX - ng * HRY) >> 8;
        if ((x + HPW <= 0) | (x >= (int32_t)HBW) | (y + HPH <= 0) |
            (y >= (int32_t)HPH)) {
          HSKIP->setPixel(ng, mg, 1);
        } else {
          HSKIP->setPixel(ng, mg, 0);
        }
      }
    }
  }
  HBPP = 1;
  while ((FX_DWORD)(1 << HBPP) < HNUMPATS) {
    HBPP++;
  }
  nonstd::unique_ptr<CJBig2_GSIDProc> pGID(new CJBig2_GSIDProc());
  pGID->GSMMR = HMMR;
  pGID->GSW = HGW;
  pGID->GSH = HGH;
  pGID->GSBPP = (uint8_t)HBPP;
  pGID->GSUSESKIP = HENABLESKIP;
  pGID->GSKIP = HSKIP.get();
  pGID->GSTEMPLATE = HTEMPLATE;
  GI = pGID->decode_Arith(pArithDecoder, gbContext, pPause);
  if (!GI)
    return nullptr;

  for (mg = 0; mg < HGH; mg++) {
    for (ng = 0; ng < HGW; ng++) {
      x = (HGX + mg * HRY + ng * HRX) >> 8;
      y = (HGY + mg * HRX - ng * HRY) >> 8;
      FX_DWORD pat_index = GI[mg * HGW + ng];
      if (pat_index >= HNUMPATS) {
        pat_index = HNUMPATS - 1;
      }
      HTREG->composeFrom(x, y, HPATS[pat_index], HCOMBOP);
    }
  }
  FX_Free(GI);
  return HTREG.release();
}

CJBig2_Image* CJBig2_HTRDProc::decode_MMR(CJBig2_BitStream* pStream,
                                          IFX_Pause* pPause) {
  FX_DWORD ng, mg;
  int32_t x, y;
  FX_DWORD* GI;
  nonstd::unique_ptr<CJBig2_Image> HTREG(new CJBig2_Image(HBW, HBH));
  HTREG->fill(HDEFPIXEL);
  FX_DWORD HBPP = 1;
  while ((FX_DWORD)(1 << HBPP) < HNUMPATS) {
    HBPP++;
  }
  nonstd::unique_ptr<CJBig2_GSIDProc> pGID(new CJBig2_GSIDProc());
  pGID->GSMMR = HMMR;
  pGID->GSW = HGW;
  pGID->GSH = HGH;
  pGID->GSBPP = (uint8_t)HBPP;
  pGID->GSUSESKIP = 0;
  GI = pGID->decode_MMR(pStream, pPause);
  if (!GI)
    return nullptr;

  for (mg = 0; mg < HGH; mg++) {
    for (ng = 0; ng < HGW; ng++) {
      x = (HGX + mg * HRY + ng * HRX) >> 8;
      y = (HGY + mg * HRX - ng * HRY) >> 8;
      FX_DWORD pat_index = GI[mg * HGW + ng];
      if (pat_index >= HNUMPATS) {
        pat_index = HNUMPATS - 1;
      }
      HTREG->composeFrom(x, y, HPATS[pat_index], HCOMBOP);
    }
  }
  FX_Free(GI);
  return HTREG.release();
}
