// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "printing/emf_win.h"

#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/win/scoped_gdi_object.h"
#include "base/win/scoped_hdc.h"
#include "base/win/scoped_select_object.h"
#include "skia/ext/vector_platform_device_emf_win.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/gdi_util.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"

namespace {

const int kCustomGdiCommentSignature = 0xdeadbabe;
struct PageBreakRecord {
  int signature;
  enum PageBreakType {
    START_PAGE,
    END_PAGE,
  } type;
  explicit PageBreakRecord(PageBreakType type_in)
      : signature(kCustomGdiCommentSignature), type(type_in) {
  }
  bool IsValid() const {
    return (signature == kCustomGdiCommentSignature) &&
           (type >= START_PAGE) && (type <= END_PAGE);
  }
};

int CALLBACK IsAlphaBlendUsedEnumProc(HDC,
                                      HANDLETABLE*,
                                      const ENHMETARECORD *record,
                                      int,
                                      LPARAM data) {
  bool* result = reinterpret_cast<bool*>(data);
  if (!result)
    return 0;
  switch (record->iType) {
    case EMR_ALPHABLEND: {
      *result = true;
      return 0;
      break;
    }
  }
  return 1;
}

int CALLBACK RasterizeAlphaBlendProc(HDC metafile_dc,
                                     HANDLETABLE* handle_table,
                                     const ENHMETARECORD *record,
                                     int num_objects,
                                     LPARAM data) {
    HDC bitmap_dc = *reinterpret_cast<HDC*>(data);
    // Play this command to the bitmap DC.
    ::PlayEnhMetaFileRecord(bitmap_dc, handle_table, record, num_objects);
    switch (record->iType) {
    case EMR_ALPHABLEND: {
      const EMRALPHABLEND* alpha_blend =
          reinterpret_cast<const EMRALPHABLEND*>(record);
      // Don't modify transformation here.
      // Old implementation did reset transformations for DC to identity matrix.
      // That was not correct and cause some bugs, like unexpected cropping.
      // EMRALPHABLEND is rendered into bitmap and metafile contexts with
      // current transformation. If we don't touch them here BitBlt will copy
      // same areas.
      ::BitBlt(metafile_dc,
               alpha_blend->xDest,
               alpha_blend->yDest,
               alpha_blend->cxDest,
               alpha_blend->cyDest,
               bitmap_dc,
               alpha_blend->xDest,
               alpha_blend->yDest,
               SRCCOPY);
      break;
    }
    case EMR_CREATEBRUSHINDIRECT:
    case EMR_CREATECOLORSPACE:
    case EMR_CREATECOLORSPACEW:
    case EMR_CREATEDIBPATTERNBRUSHPT:
    case EMR_CREATEMONOBRUSH:
    case EMR_CREATEPALETTE:
    case EMR_CREATEPEN:
    case EMR_DELETECOLORSPACE:
    case EMR_DELETEOBJECT:
    case EMR_EXTCREATEFONTINDIRECTW:
      // Play object creation command only once.
      break;

    default:
      // Play this command to the metafile DC.
      ::PlayEnhMetaFileRecord(metafile_dc, handle_table, record, num_objects);
      break;
    }
    return 1;  // Continue enumeration
}

// Bitmapt for rasterization.
class RasterBitmap {
 public:
  explicit RasterBitmap(const gfx::Size& raster_size)
      : saved_object_(NULL) {
    context_.Set(::CreateCompatibleDC(NULL));
    if (!context_) {
      NOTREACHED() << "Bitmap DC creation failed";
      return;
    }
    ::SetGraphicsMode(context_, GM_ADVANCED);
    void* bits = NULL;
    gfx::Rect bitmap_rect(raster_size);
    gfx::CreateBitmapHeader(raster_size.width(), raster_size.height(),
                            &header_.bmiHeader);
    bitmap_.Set(::CreateDIBSection(context_, &header_, DIB_RGB_COLORS, &bits,
                                   NULL, 0));
    if (!bitmap_)
      NOTREACHED() << "Raster bitmap creation for printing failed";

    saved_object_ = ::SelectObject(context_, bitmap_);
    RECT rect = bitmap_rect.ToRECT();
    ::FillRect(context_, &rect,
               static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH)));

  }

  ~RasterBitmap() {
    ::SelectObject(context_, saved_object_);
  }

  HDC context() const {
    return context_;
  }

  base::win::ScopedCreateDC context_;
  BITMAPINFO header_;
  base::win::ScopedBitmap bitmap_;
  HGDIOBJ saved_object_;

 private:
  DISALLOW_COPY_AND_ASSIGN(RasterBitmap);
};



}  // namespace

namespace printing {

bool DIBFormatNativelySupported(HDC dc, uint32 escape, const BYTE* bits,
                                int size) {
  BOOL supported = FALSE;
  if (ExtEscape(dc, QUERYESCSUPPORT, sizeof(escape),
                reinterpret_cast<LPCSTR>(&escape), 0, 0) > 0) {
    ExtEscape(dc, escape, size, reinterpret_cast<LPCSTR>(bits),
              sizeof(supported), reinterpret_cast<LPSTR>(&supported));
  }
  return !!supported;
}

Emf::Emf() : emf_(NULL), hdc_(NULL), page_count_(0) {
}

Emf::~Emf() {
  DCHECK(!hdc_);
  if (emf_)
    DeleteEnhMetaFile(emf_);
}

bool Emf::InitToFile(const base::FilePath& metafile_path) {
  DCHECK(!emf_ && !hdc_);
  hdc_ = CreateEnhMetaFile(NULL, metafile_path.value().c_str(), NULL, NULL);
  DCHECK(hdc_);
  return hdc_ != NULL;
}

bool Emf::InitFromFile(const base::FilePath& metafile_path) {
  DCHECK(!emf_ && !hdc_);
  emf_ = GetEnhMetaFile(metafile_path.value().c_str());
  DCHECK(emf_);
  return emf_ != NULL;
}

bool Emf::Init() {
  DCHECK(!emf_ && !hdc_);
  hdc_ = CreateEnhMetaFile(NULL, NULL, NULL, NULL);
  DCHECK(hdc_);
  return hdc_ != NULL;
}

bool Emf::InitFromData(const void* src_buffer, uint32 src_buffer_size) {
  DCHECK(!emf_ && !hdc_);
  emf_ = SetEnhMetaFileBits(src_buffer_size,
                            reinterpret_cast<const BYTE*>(src_buffer));
  return emf_ != NULL;
}

bool Emf::FinishDocument() {
  DCHECK(!emf_ && hdc_);
  emf_ = CloseEnhMetaFile(hdc_);
  DCHECK(emf_);
  hdc_ = NULL;
  return emf_ != NULL;
}

bool Emf::Playback(HDC hdc, const RECT* rect) const {
  DCHECK(emf_ && !hdc_);
  RECT bounds;
  if (!rect) {
    // Get the natural bounds of the EMF buffer.
    bounds = GetPageBounds(1).ToRECT();
    rect = &bounds;
  }
  return PlayEnhMetaFile(hdc, emf_, rect) != 0;
}

bool Emf::SafePlayback(HDC context) const {
  DCHECK(emf_ && !hdc_);
  XFORM base_matrix;
  if (!GetWorldTransform(context, &base_matrix)) {
    NOTREACHED();
    return false;
  }
  Emf::EnumerationContext playback_context;
  playback_context.base_matrix = &base_matrix;
  RECT rect = GetPageBounds(1).ToRECT();
  return EnumEnhMetaFile(context,
                         emf_,
                         &Emf::SafePlaybackProc,
                         reinterpret_cast<void*>(&playback_context),
                         &rect) != 0;
}

gfx::Rect Emf::GetPageBounds(unsigned int page_number) const {
  DCHECK(emf_ && !hdc_);
  DCHECK_EQ(1U, page_number);
  ENHMETAHEADER header;
  if (GetEnhMetaFileHeader(emf_, sizeof(header), &header) != sizeof(header)) {
    NOTREACHED();
    return gfx::Rect();
  }
  // Add 1 to right and bottom because it's inclusive rectangle.
  // See ENHMETAHEADER.
  return gfx::Rect(header.rclBounds.left,
                   header.rclBounds.top,
                   header.rclBounds.right - header.rclBounds.left + 1,
                   header.rclBounds.bottom - header.rclBounds.top + 1);
}

uint32 Emf::GetDataSize() const {
  DCHECK(emf_ && !hdc_);
  return GetEnhMetaFileBits(emf_, 0, NULL);
}

bool Emf::GetData(void* buffer, uint32 size) const {
  DCHECK(emf_ && !hdc_);
  DCHECK(buffer && size);
  uint32 size2 =
      GetEnhMetaFileBits(emf_, size, reinterpret_cast<BYTE*>(buffer));
  DCHECK(size2 == size);
  return size2 == size && size2 != 0;
}

bool Emf::GetDataAsVector(std::vector<uint8>* buffer) const {
  uint32 size = GetDataSize();
  if (!size)
    return false;

  buffer->resize(size);
  if (!GetData(&buffer->front(), size))
    return false;
  return true;
}

bool Emf::SaveTo(const base::FilePath& file_path) const {
  HANDLE file = CreateFile(file_path.value().c_str(), GENERIC_WRITE,
                           FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
                           CREATE_ALWAYS, 0, NULL);
  if (file == INVALID_HANDLE_VALUE)
    return false;

  bool success = false;
  std::vector<uint8> buffer;
  if (GetDataAsVector(&buffer)) {
    DWORD written = 0;
    if (WriteFile(file, &*buffer.begin(), static_cast<DWORD>(buffer.size()),
                  &written, NULL) &&
        written == buffer.size()) {
      success = true;
    }
  }
  CloseHandle(file);
  return success;
}

int CALLBACK Emf::SafePlaybackProc(HDC hdc,
                                   HANDLETABLE* handle_table,
                                   const ENHMETARECORD* record,
                                   int objects_count,
                                   LPARAM param) {
  Emf::EnumerationContext* context =
      reinterpret_cast<Emf::EnumerationContext*>(param);
  context->handle_table = handle_table;
  context->objects_count = objects_count;
  context->hdc = hdc;
  Record record_instance(record);
  bool success = record_instance.SafePlayback(context);
  DCHECK(success);
  return 1;
}

Emf::EnumerationContext::EnumerationContext() {
  memset(this, 0, sizeof(*this));
}

Emf::Record::Record(const ENHMETARECORD* record)
    : record_(record) {
  DCHECK(record_);
}

bool Emf::Record::Play(Emf::EnumerationContext* context) const {
  return 0 != PlayEnhMetaFileRecord(context->hdc,
                                    context->handle_table,
                                    record_,
                                    context->objects_count);
}

bool Emf::Record::SafePlayback(Emf::EnumerationContext* context) const {
  // For EMF field description, see [MS-EMF] Enhanced Metafile Format
  // Specification.
  //
  // This is the second major EMF breakage I get; the first one being
  // SetDCBrushColor/SetDCPenColor/DC_PEN/DC_BRUSH being silently ignored.
  //
  // This function is the guts of the fix for bug 1186598. Some printer drivers
  // somehow choke on certain EMF records, but calling the corresponding
  // function directly on the printer HDC is fine. Still, playing the EMF record
  // fails. Go figure.
  //
  // The main issue is that SetLayout is totally unsupported on these printers
  // (HP 4500/4700). I used to call SetLayout and I stopped. I found out this is
  // not sufficient because GDI32!PlayEnhMetaFile internally calls SetLayout(!)
  // Damn.
  //
  // So I resorted to manually parse the EMF records and play them one by one.
  // The issue with this method compared to using PlayEnhMetaFile to play back
  // an EMF buffer is that the later silently fixes the matrix to take in
  // account the matrix currently loaded at the time of the call.
  // The matrix magic is done transparently when using PlayEnhMetaFile but since
  // I'm processing one field at a time, I need to do the fixup myself. Note
  // that PlayEnhMetaFileRecord doesn't fix the matrix correctly even when
  // called inside an EnumEnhMetaFile loop. Go figure (bis).
  //
  // So when I see a EMR_SETWORLDTRANSFORM and EMR_MODIFYWORLDTRANSFORM, I need
  // to fix the matrix according to the matrix previously loaded before playing
  // back the buffer. Otherwise, the previously loaded matrix would be ignored
  // and the EMF buffer would always be played back at its native resolution.
  // Duh.
  //
  // I also use this opportunity to skip over eventual EMR_SETLAYOUT record that
  // could remain.
  //
  // Another tweak we make is for JPEGs/PNGs in calls to StretchDIBits.
  // (Our Pepper plugin code uses a JPEG). If the printer does not support
  // JPEGs/PNGs natively we decompress the JPEG/PNG and then set it to the
  // device.
  // TODO(sanjeevr): We should also add JPEG/PNG support for SetSIBitsToDevice
  //
  // We also process any custom EMR_GDICOMMENT records which are our
  // placeholders for StartPage and EndPage.
  // Note: I should probably care about view ports and clipping, eventually.
  bool res = false;
  const XFORM* base_matrix = context->base_matrix;
  switch (record()->iType) {
    case EMR_STRETCHDIBITS: {
      const EMRSTRETCHDIBITS * sdib_record =
          reinterpret_cast<const EMRSTRETCHDIBITS*>(record());
      const BYTE* record_start = reinterpret_cast<const BYTE *>(record());
      const BITMAPINFOHEADER *bmih =
          reinterpret_cast<const BITMAPINFOHEADER *>(record_start +
                                                     sdib_record->offBmiSrc);
      const BYTE* bits = record_start + sdib_record->offBitsSrc;
      bool play_normally = true;
      res = false;
      HDC hdc = context->hdc;
      scoped_ptr<SkBitmap> bitmap;
      if (bmih->biCompression == BI_JPEG) {
        if (!DIBFormatNativelySupported(hdc, CHECKJPEGFORMAT, bits,
                                        bmih->biSizeImage)) {
          play_normally = false;
          bitmap.reset(gfx::JPEGCodec::Decode(bits, bmih->biSizeImage));
        }
      } else if (bmih->biCompression == BI_PNG) {
        if (!DIBFormatNativelySupported(hdc, CHECKPNGFORMAT, bits,
                                        bmih->biSizeImage)) {
          play_normally = false;
          bitmap.reset(new SkBitmap());
          gfx::PNGCodec::Decode(bits, bmih->biSizeImage, bitmap.get());
        }
      }
      if (!play_normally) {
        DCHECK(bitmap.get());
        if (bitmap.get()) {
          SkAutoLockPixels lock(*bitmap.get());
          DCHECK_EQ(bitmap->colorType(), kN32_SkColorType);
          const uint32_t* pixels =
              static_cast<const uint32_t*>(bitmap->getPixels());
          if (pixels == NULL) {
            NOTREACHED();
            return false;
          }
          BITMAPINFOHEADER bmi = {0};
          gfx::CreateBitmapHeader(bitmap->width(), bitmap->height(), &bmi);
          res = (0 != StretchDIBits(hdc, sdib_record->xDest, sdib_record->yDest,
                                    sdib_record->cxDest,
                                    sdib_record->cyDest, sdib_record->xSrc,
                                    sdib_record->ySrc,
                                    sdib_record->cxSrc, sdib_record->cySrc,
                                    pixels,
                                    reinterpret_cast<const BITMAPINFO *>(&bmi),
                                    sdib_record->iUsageSrc,
                                    sdib_record->dwRop));
        }
      } else {
        res = Play(context);
      }
      break;
    }
    case EMR_SETWORLDTRANSFORM: {
      DCHECK_EQ(record()->nSize, sizeof(DWORD) * 2 + sizeof(XFORM));
      const XFORM* xform = reinterpret_cast<const XFORM*>(record()->dParm);
      HDC hdc = context->hdc;
      if (base_matrix) {
        res = 0 != SetWorldTransform(hdc, base_matrix) &&
                   ModifyWorldTransform(hdc, xform, MWT_LEFTMULTIPLY);
      } else {
        res = 0 != SetWorldTransform(hdc, xform);
      }
      break;
    }
    case EMR_MODIFYWORLDTRANSFORM: {
      DCHECK_EQ(record()->nSize,
                sizeof(DWORD) * 2 + sizeof(XFORM) + sizeof(DWORD));
      const XFORM* xform = reinterpret_cast<const XFORM*>(record()->dParm);
      const DWORD* option = reinterpret_cast<const DWORD*>(xform + 1);
      HDC hdc = context->hdc;
      switch (*option) {
        case MWT_IDENTITY:
          if (base_matrix) {
            res = 0 != SetWorldTransform(hdc, base_matrix);
          } else {
            res = 0 != ModifyWorldTransform(hdc, xform, MWT_IDENTITY);
          }
          break;
        case MWT_LEFTMULTIPLY:
        case MWT_RIGHTMULTIPLY:
          res = 0 != ModifyWorldTransform(hdc, xform, *option);
          break;
        case 4:  // MWT_SET
          if (base_matrix) {
            res = 0 != SetWorldTransform(hdc, base_matrix) &&
                       ModifyWorldTransform(hdc, xform, MWT_LEFTMULTIPLY);
          } else {
            res = 0 != SetWorldTransform(hdc, xform);
          }
          break;
        default:
          res = false;
          break;
      }
      break;
    }
    case EMR_SETLAYOUT:
      // Ignore it.
      res = true;
      break;
    case EMR_GDICOMMENT: {
      const EMRGDICOMMENT* comment_record =
          reinterpret_cast<const EMRGDICOMMENT*>(record());
      if (comment_record->cbData == sizeof(PageBreakRecord)) {
        const PageBreakRecord* page_break_record =
            reinterpret_cast<const PageBreakRecord*>(comment_record->Data);
        if (page_break_record && page_break_record->IsValid()) {
          if (page_break_record->type == PageBreakRecord::START_PAGE) {
            res = !!::StartPage(context->hdc);
            DCHECK_EQ(0, context->dc_on_page_start);
            context->dc_on_page_start = ::SaveDC(context->hdc);
          } else if (page_break_record->type == PageBreakRecord::END_PAGE) {
            DCHECK_NE(0, context->dc_on_page_start);
            ::RestoreDC(context->hdc, context->dc_on_page_start);
            context->dc_on_page_start = 0;
            res = !!::EndPage(context->hdc);
          } else {
            res = false;
            NOTREACHED();
          }
        } else {
          res = Play(context);
        }
      } else {
        res = true;
      }
      break;
    }
    default: {
      res = Play(context);
      break;
    }
  }
  return res;
}

SkBaseDevice* Emf::StartPageForVectorCanvas(
    const gfx::Size& page_size, const gfx::Rect& content_area,
    const float& scale_factor) {
  if (!StartPage(page_size, content_area, scale_factor))
    return NULL;

  return skia::VectorPlatformDeviceEmf::CreateDevice(page_size.width(),
                                                     page_size.height(),
                                                     true, hdc_);
}

bool Emf::StartPage(const gfx::Size& /*page_size*/,
                    const gfx::Rect& /*content_area*/,
                    const float& /*scale_factor*/) {
  DCHECK(hdc_);
  if (!hdc_)
    return false;
  page_count_++;
  PageBreakRecord record(PageBreakRecord::START_PAGE);
  return !!GdiComment(hdc_, sizeof(record),
                      reinterpret_cast<const BYTE *>(&record));
}

bool Emf::FinishPage() {
  DCHECK(hdc_);
  if (!hdc_)
    return false;
  PageBreakRecord record(PageBreakRecord::END_PAGE);
  return !!GdiComment(hdc_, sizeof(record),
                      reinterpret_cast<const BYTE *>(&record));
}

Emf::Enumerator::Enumerator(const Emf& emf, HDC context, const RECT* rect) {
  items_.clear();
  if (!EnumEnhMetaFile(context,
                       emf.emf(),
                       &Emf::Enumerator::EnhMetaFileProc,
                       reinterpret_cast<void*>(this),
                       rect)) {
    NOTREACHED();
    items_.clear();
  }
  DCHECK_EQ(context_.hdc, context);
}

Emf::Enumerator::const_iterator Emf::Enumerator::begin() const {
  return items_.begin();
}

Emf::Enumerator::const_iterator Emf::Enumerator::end() const {
  return items_.end();
}

int CALLBACK Emf::Enumerator::EnhMetaFileProc(HDC hdc,
                                              HANDLETABLE* handle_table,
                                              const ENHMETARECORD* record,
                                              int objects_count,
                                              LPARAM param) {
  Enumerator& emf = *reinterpret_cast<Enumerator*>(param);
  if (!emf.context_.handle_table) {
    DCHECK(!emf.context_.handle_table);
    DCHECK(!emf.context_.objects_count);
    emf.context_.handle_table = handle_table;
    emf.context_.objects_count = objects_count;
    emf.context_.hdc = hdc;
  } else {
    DCHECK_EQ(emf.context_.handle_table, handle_table);
    DCHECK_EQ(emf.context_.objects_count, objects_count);
    DCHECK_EQ(emf.context_.hdc, hdc);
  }
  emf.items_.push_back(Record(record));
  return 1;
}

bool Emf::IsAlphaBlendUsed() const {
  bool result = false;
  ::EnumEnhMetaFile(NULL,
                    emf(),
                    &IsAlphaBlendUsedEnumProc,
                    &result,
                    NULL);
  return result;
}

Emf* Emf::RasterizeMetafile(int raster_area_in_pixels) const {
  gfx::Rect page_bounds = GetPageBounds(1);
  gfx::Size page_size(page_bounds.size());
  if (page_size.GetArea() <= 0) {
    NOTREACHED() << "Metafile is empty";
    page_bounds = gfx::Rect(1, 1);
  }

  float scale = sqrt(float(raster_area_in_pixels) / page_size.GetArea());
  page_size.set_width(std::max<int>(1, page_size.width() * scale));
  page_size.set_height(std::max<int>(1, page_size.height() * scale));


  RasterBitmap bitmap(page_size);

  gfx::Rect bitmap_rect(page_size);
  RECT rect = bitmap_rect.ToRECT();
  Playback(bitmap.context(), &rect);

  scoped_ptr<Emf> result(new Emf);
  result->Init();
  HDC hdc = result->context();
  DCHECK(hdc);
  skia::InitializeDC(hdc);

  // Params are ignored.
  result->StartPage(page_bounds.size(), page_bounds, 1);

  ::ModifyWorldTransform(hdc, NULL, MWT_IDENTITY);
  XFORM xform = {
    float(page_bounds.width()) / bitmap_rect.width(), 0,
    0, float(page_bounds.height()) / bitmap_rect.height(),
    page_bounds.x(),
    page_bounds.y(),
  };
  ::SetWorldTransform(hdc, &xform);
  ::BitBlt(hdc, 0, 0, bitmap_rect.width(), bitmap_rect.height(),
           bitmap.context(), bitmap_rect.x(), bitmap_rect.y(), SRCCOPY);

  result->FinishPage();
  result->FinishDocument();

  return result.release();
}

Emf* Emf::RasterizeAlphaBlend() const {
  gfx::Rect page_bounds = GetPageBounds(1);
  if (page_bounds.size().GetArea() <= 0) {
    NOTREACHED() << "Metafile is empty";
    page_bounds = gfx::Rect(1, 1);
  }

  RasterBitmap bitmap(page_bounds.size());

  // Map metafile page_bounds.x(), page_bounds.y() to bitmap 0, 0.
  XFORM xform = { 1, 0, 0, 1, -page_bounds.x(), -page_bounds.y()};
  ::SetWorldTransform(bitmap.context(), &xform);

  scoped_ptr<Emf> result(new Emf);
  result->Init();
  HDC hdc = result->context();
  DCHECK(hdc);
  skia::InitializeDC(hdc);

  HDC bitmap_dc = bitmap.context();
  RECT rect = page_bounds.ToRECT();
  ::EnumEnhMetaFile(hdc, emf(), &RasterizeAlphaBlendProc, &bitmap_dc, &rect);

  result->FinishDocument();

  return result.release();
}


}  // namespace printing
