// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "renderer/win32/win32_renderer_util.h"

#define _ATL_NO_AUTOMATIC_NAMESPACE
#define _WTL_NO_AUTOMATIC_NAMESPACE
#include <atlbase.h>
#include <atlapp.h>
#include <atlgdi.h>
#include <atlmisc.h>

// undef min macro, which conflicts with std::numeric_limits<int>::min().
#if defined(min)
#undef min
#endif  // min

// undef max macro, which conflicts with std::numeric_limits<int>::max().
#if defined(max)
#undef max
#endif  // max

#include <limits>
#include <memory>
#include <string>
#include <vector>

#include "base/logging.h"
#include "base/util.h"
#include "base/win_util.h"
#include "renderer/renderer_command.pb.h"
#include "renderer/win32/win32_font_util.h"

namespace mozc {
namespace renderer {
namespace win32 {
using ATL::CWindow;
using WTL::CDC;
using WTL::CDCHandle;
using WTL::CSize;
using WTL::CRect;
using WTL::CPoint;
using WTL::CFont;
using WTL::CFontHandle;
using WTL::CLogFont;
using std::unique_ptr;

typedef mozc::commands::RendererCommand::CompositionForm CompositionForm;
typedef mozc::commands::RendererCommand::CandidateForm CandidateForm;

namespace {
// This template class is used to represent rendering information which may
// or may not be available depends on the application and operations.
template <typename T>
class Optional {
 public:
  Optional()
    : value_(T()),
      has_value_(false) {}

  explicit Optional(const T &src)
    : value_(src),
      has_value_(true) {}

  const T &value() const {
    DCHECK(has_value_);
    return value_;
  }

  T *mutable_value() {
    has_value_ = true;
    return &value_;
  }

  bool has_value() const {
    return has_value_;
  }

  void Clear() {
    has_value_ = false;
  }

 private:
  T value_;
  bool has_value_;
};

// A set of rendering information relevant to the target application.  Note
// that all of the positional fields are (logical) screen coordinates.
struct CandidateWindowLayoutParams {
  Optional<HWND> window_handle;
  Optional<IMECHARPOSITION> char_pos;
  Optional<CPoint> composition_form_topleft;
  Optional<CandidateWindowLayout> candidate_form;
  Optional<CRect> caret_rect;
  Optional<CLogFont> composition_font;
  Optional<CLogFont> default_gui_font;
  Optional<CRect> client_rect;
  Optional<bool> vertical_writing;
};

bool IsValidRect(const commands::RendererCommand::Rectangle &rect) {
  return rect.has_left() && rect.has_top() &&
         rect.has_right() && rect.has_bottom();
}

CRect ToRect(const commands::RendererCommand::Rectangle &rect) {
  DCHECK(IsValidRect(rect));
  return CRect(rect.left(), rect.top(), rect.right(), rect.bottom());
}

bool IsValidPoint(const commands::RendererCommand::Point &point) {
  return point.has_x() && point.has_y();
}

CPoint ToPoint(const commands::RendererCommand::Point &point) {
  DCHECK(IsValidPoint(point));
  return CPoint(point.x(), point.y());
}

// Returns an absolute font height of the composition font.
// Note that this function does not take the DPI virtualization into
// consideration so the caller is responsible to multiply an appropriate
// scaling factor.
// If a composition font is not available, this function try to use
// the default GUI font on this session.
int GetAbsoluteFontHeight(const CandidateWindowLayoutParams &params) {
  // A negative font height is also valid in the LONGFONT structure.
  // Use |abs| for normalization.
  // http://msdn.microsoft.com/en-us/library/dd145037.aspx
  if (params.composition_font.has_value()) {
    return abs(params.composition_font.value().lfHeight);
  }
  if (params.default_gui_font.has_value()) {
    return abs(params.default_gui_font.value().lfHeight);
  }
  return 0;
}

// "base_pos" is an ideal position where the candidate window is placed.
// Basically the ideal position depends on historical reason for each
// country and language.
// As for Japanese IME, the bottom-left (for horizontal writing) and
// top-left (for vertical writing) corner of the target segment have been
// used for many years.
CPoint GetBasePositionFromExcludeRect(const CRect &exclude_rect,
                                      bool is_vertical) {
  if (is_vertical) {
    // Vertical
    return exclude_rect.TopLeft();
  }

  // Horizontal
  return CPoint(exclude_rect.left, exclude_rect.bottom);
}

// Returns false if given |form| should be ignored for some compatibility
// reason.  Otherwise, returns true.
bool IsCompatibleCompositionForm(const CompositionForm &form,
                                 int compatibility_mode) {
  // If IGNORE_DEFAULT_COMPOSITION_FORM flag is specified and all the fields
  // in the CompositionForm is 0, returns false.
  if ((compatibility_mode & IGNORE_DEFAULT_COMPOSITION_FORM) !=
      IGNORE_DEFAULT_COMPOSITION_FORM) {
    return true;
  }

  // TODO(yukawa): Stop supporting |deprecated_style()|.
  const uint32 style_bits =
      (form.has_deprecated_style() ? form.deprecated_style()
                                   : form.style_bits());

  // Note that CompositionForm::DEFAULT is defined as 0.
  if (style_bits != CompositionForm::DEFAULT) {
    return true;
  }

  if (!IsValidPoint(form.current_position())) {
    return true;
  }
  const CPoint current_position = ToPoint(form.current_position());
  if (current_position != CPoint(0, 0)) {
    return true;
  }

  if (!IsValidRect(form.area())) {
    return true;
  }
  const CRect area = ToRect(form.area());
  if (!area.IsRectNull()) {
    return true;
  }

  return false;
}

bool ExtractParams(
    LayoutManager *layout,
    int compatibility_mode,
    const commands::RendererCommand::ApplicationInfo &app_info,
    CandidateWindowLayoutParams *params) {
  DCHECK_NE(NULL, layout);
  DCHECK_NE(NULL, params);

  params->window_handle.Clear();
  params->char_pos.Clear();
  params->composition_form_topleft.Clear();
  params->candidate_form.Clear();
  params->caret_rect.Clear();
  params->composition_font.Clear();
  params->default_gui_font.Clear();
  params->client_rect.Clear();
  params->vertical_writing.Clear();

  if (!app_info.has_target_window_handle()) {
    return false;
  }
  const HWND target_window = reinterpret_cast<HWND>(
      app_info.target_window_handle());

  *params->window_handle.mutable_value() = target_window;

  if (app_info.has_composition_target()) {
    const commands::RendererCommand::CharacterPosition &char_pos =
        app_info.composition_target();
    // Check the availability of optional fields.
    if (char_pos.has_position() &&
        char_pos.has_top_left() &&
        IsValidPoint(char_pos.top_left()) &&
        char_pos.has_line_height() &&
        char_pos.line_height() > 0 &&
        char_pos.has_document_area() &&
        IsValidRect(char_pos.document_area())) {
      // Positional fields are (logical) screen coordinate.
      IMECHARPOSITION *dest = params->char_pos.mutable_value();
      dest->dwCharPos = char_pos.position();
      dest->pt = ToPoint(char_pos.top_left());
      dest->cLineHeight = char_pos.line_height();
      dest->rcDocument = ToRect(char_pos.document_area());
    }
  }

  if (app_info.has_composition_form()) {
    const commands::RendererCommand::CompositionForm &form =
        app_info.composition_form();

    // Check the availability of optional fields.
    if (form.has_current_position() &&
        IsValidPoint(form.current_position()) &&
        IsCompatibleCompositionForm(form, compatibility_mode)) {
      Optional<CPoint> screen_pos;
      if (!layout->ClientPointToScreen(
              target_window, ToPoint(form.current_position()),
              params->composition_form_topleft.mutable_value())) {
        params->composition_form_topleft.Clear();
      }
    }
  }

  if (app_info.has_candidate_form()) {
    const commands::RendererCommand::CandidateForm &form =
        app_info.candidate_form();

    // TODO(yukawa): Stop supporting |deprecated_style()|.
    const uint32 candidate_style_bits =
        (form.has_deprecated_style() ? form.deprecated_style()
                                     : form.style_bits());

    const bool has_candidate_pos_style_bit =
        ((candidate_style_bits & CandidateForm::CANDIDATEPOS) ==
         CandidateForm::CANDIDATEPOS);

    const bool has_exclude_style_bit =
        ((candidate_style_bits & CandidateForm::EXCLUDE) ==
         CandidateForm::EXCLUDE);

    // Check the availability of optional fields.
    if ((has_candidate_pos_style_bit || has_exclude_style_bit) &&
        form.has_current_position() &&
        IsValidPoint(form.current_position())) {
      const bool use_local_coord =
          (compatibility_mode & USE_LOCAL_COORD_FOR_CANDIDATE_FORM) ==
          USE_LOCAL_COORD_FOR_CANDIDATE_FORM;
      Optional<CPoint> screen_pos;
      if (use_local_coord) {
        if (!layout->LocalPointToScreen(
                target_window, ToPoint(form.current_position()),
                screen_pos.mutable_value())) {
          screen_pos.Clear();
        }
      } else {
        if (!layout->ClientPointToScreen(
                target_window, ToPoint(form.current_position()),
                screen_pos.mutable_value())) {
          screen_pos.Clear();
        }
      }
      if (screen_pos.has_value()) {
        // Here, we got an appropriate position where the candidate window
        // can be placed.
        params->candidate_form.mutable_value()->
            InitializeWithPosition(screen_pos.value());

        // If |CandidateForm::EXCLUDE| is specified, try to use the |area|
        // field as an exclude region.
        if (has_exclude_style_bit &&
            form.has_area() &&
            IsValidRect(form.area())) {
          Optional<CRect> screen_rect;
          if (use_local_coord) {
            if (!layout->LocalRectToScreen(
                    target_window, ToRect(form.area()),
                    screen_rect.mutable_value())) {
              screen_rect.Clear();
            }
          } else {
            if (!layout->ClientRectToScreen(
                    target_window, ToRect(form.area()),
                    screen_rect.mutable_value())) {
              screen_rect.Clear();
            }
          }
          if (screen_rect.has_value()) {
            // Here we got an appropriate exclude region too.
            // Update the |candidate_form| with them.
            params->candidate_form.mutable_value()->
                InitializeWithPositionAndExcludeRegion(
                    screen_pos.value(), screen_rect.value());
          }
        }
      }
    }
  }

  if (app_info.has_caret_info()) {
    const commands::RendererCommand::CaretInfo &caret_info =
        app_info.caret_info();

    // Check the availability of optional fields.
    if (caret_info.has_blinking() &&
        caret_info.has_caret_rect() &&
        IsValidRect(caret_info.caret_rect()) &&
        caret_info.has_target_window_handle()) {
      const HWND caret_window = reinterpret_cast<HWND>(
          caret_info.target_window_handle());
      const CRect caret_rect_in_client_coord(ToRect(caret_info.caret_rect()));
      // It seems (0, 0, 0, 0) represents that the application does not have a
      // valid caret now.
      if (!caret_rect_in_client_coord.IsRectNull()) {
        if (!layout->ClientRectToScreen(
                caret_window, caret_rect_in_client_coord,
                params->caret_rect.mutable_value())) {
          params->caret_rect.Clear();
        }
      }
    }
  }

  if (app_info.has_composition_font()) {
    if (!mozc::win32::FontUtil::ToLOGFONT(
            app_info.composition_font(),
            params->composition_font.mutable_value())) {
      params->composition_font.Clear();
    }
  }

  if (!layout->GetDefaultGuiFont(params->default_gui_font.mutable_value())) {
    params->default_gui_font.Clear();
  }

  {
    CRect client_rect_in_local_coord;
    CRect client_rect_in_logical_screen_coord;
    if (layout->GetClientRect(target_window, &client_rect_in_local_coord) &&
        layout->ClientRectToScreen(
            target_window, client_rect_in_local_coord,
            &client_rect_in_logical_screen_coord)) {
      *params->client_rect.mutable_value() =
          client_rect_in_logical_screen_coord;
    }
  }

  {
    const LayoutManager::WritingDirection direction =
        layout->GetWritingDirection(app_info);
    if (direction == LayoutManager::VERTICAL_WRITING) {
      *params->vertical_writing.mutable_value() = true;
    } else if (direction == LayoutManager::HORIZONTAL_WRITING) {
      *params->vertical_writing.mutable_value() = false;
    }
  }
  return true;
}

wstring ComposePreeditText(const commands::Preedit &preedit,
                           string *preedit_utf8,
                           vector<int> *segment_indices,
                           vector<CharacterRange> *segment_ranges) {
  if (preedit_utf8 != NULL) {
    preedit_utf8->clear();
  }
  if (segment_indices != NULL) {
    segment_indices->clear();
  }
  if (segment_ranges != NULL) {
    segment_ranges->clear();
  }
  wstring value;
  int total_characters = 0;
  for (size_t segment_index = 0; segment_index < preedit.segment_size();
       ++segment_index) {
    const commands::Preedit::Segment &segment = preedit.segment(segment_index);
    wstring segment_value;
    mozc::Util::UTF8ToWide(segment.value(), &segment_value);
    value.append(segment_value);
    if (preedit_utf8 != NULL) {
      preedit_utf8->append(segment.value());
    }
    const int text_length = segment_value.size();
    if (segment_indices != NULL) {
      for (size_t i = 0; i < text_length; ++i) {
        segment_indices->push_back(segment_index);
      }
    }
    if (segment_ranges != NULL) {
      CharacterRange range;
      range.begin = total_characters;
      range.length = text_length;
      segment_ranges->push_back(range);
    }
    total_characters += text_length;
  }
  return value;
}

bool CalcLayoutWithTextWrappingInternal(
    CDCHandle dc,
    const wstring &str,
    const int maximum_line_length,
    const int initial_offset,
    vector<LineLayout> *line_layouts) {
  DCHECK(line_layouts != NULL);
  if (initial_offset < 0 || maximum_line_length <= 0 ||
      maximum_line_length < initial_offset) {
    LOG(ERROR) << "(initial_offset, maximum_line_length) = ("
               << initial_offset << ", " << maximum_line_length << ")";
    return false;
  }

  TEXTMETRIC metrics = {0};
  if (!dc.GetTextMetrics(&metrics)) {
    const int error = ::GetLastError();
    LOG(ERROR) << "GetTextMetrics failed. error = " << error;
    return false;
  }

  int string_index = 0;
  int current_offset = initial_offset;
  while (true) {
    const int remaining_chars = str.size() - string_index;
    if (remaining_chars <= 0) {
      return true;
    }

    // Here we can assume the following conditions are satisfied.
    //  0 <= current_offset
    //  0 <= maximum_line_length
    //  current_offset <= maximum_line_length
    const int remaining_extent = maximum_line_length - current_offset;
    DCHECK_GE(remaining_extent, 0)
       << "(remaining_extent, maximum_line_length) = ("
       << remaining_extent << ", " << maximum_line_length << ")";
    DCHECK_GE(maximum_line_length, remaining_extent)
       << "(remaining_extent, maximum_line_length) = ("
       << remaining_extent << ", " << maximum_line_length << ")";

    int allowable_chars = 0;
    CSize dummy;
    BOOL result = dc.GetTextExtentExPoint(
        str.c_str() + string_index,
        remaining_chars,
        &dummy,
        remaining_extent,
        &allowable_chars,
        NULL);
    if (result == FALSE) {
      const int error = ::GetLastError();
      LOG(ERROR) << "GetTextExtentExPoint failed. error = " << error;
      return false;
    }

    if (allowable_chars == 0 && current_offset == 0) {
      // In this case, the region does not have enough space to display the
      // next character.
      return false;
    }

    // Just in case GetTextExtentExPoint returns true but the returned value
    // is invalid.  We have not seen any problem around this API though.
    if (allowable_chars < 0 || remaining_chars < allowable_chars) {
      // Something wrong.
      LOG(ERROR) << "(allowable_chars, remaining_chars) = ("
                 << allowable_chars << ", " << remaining_chars << ")";
      return false;
    }

    {
      LineLayout layout;
      layout.text = str.substr(string_index, allowable_chars);
      if (allowable_chars == 0) {
        // This case occurs only when this line does not have enough space to
        // render the next character from |current_offset|.  We will try to
        // render text in the next line.  Note that an infinite loop should
        // never occur because we have already checked the case above.  This is
        // why |current_offset| should be positive here.
        DCHECK_GT(current_offset, 0);
        layout.line_width = metrics.tmHeight;
      } else {
        CSize line_size;
        int allowable_chars_for_confirmation = 0;
        unique_ptr<int[]> size_buffer(new int[allowable_chars]);
        result = dc.GetTextExtentExPoint(
            layout.text.c_str(),
            layout.text.size(),
            &line_size,
            remaining_extent,
            &allowable_chars_for_confirmation,
            size_buffer.get());
        if (result == FALSE) {
          const int error = ::GetLastError();
          LOG(ERROR) << "GetTextExtentExPoint failed. error = " << error;
          return false;
        }
        if (allowable_chars != allowable_chars_for_confirmation) {
          LOG(ERROR)
              << "(allowable_chars, allowable_chars_for_confirmation) = ("
              << allowable_chars << ", "
              << allowable_chars_for_confirmation << ")";
          return false;
        }
        layout.line_length = line_size.cx;
        layout.line_width = line_size.cy;
        layout.line_start_offset = current_offset;
        int next_char_begin = 0;
        for (size_t character_index = 0; character_index < allowable_chars;
             ++character_index) {
          CharacterRange range;
          range.begin = next_char_begin;
          range.length = size_buffer[character_index] - next_char_begin;
          layout.character_positions.push_back(range);
          next_char_begin = size_buffer[character_index];
        }
      }
      DCHECK_EQ(layout.text.size(), layout.character_positions.size());
      line_layouts->push_back(layout);
    }

    string_index += allowable_chars;
    current_offset = 0;
  }

  return false;
}

class NativeSystemPreferenceAPI : public SystemPreferenceInterface {
 public:
  virtual ~NativeSystemPreferenceAPI() {}

  virtual bool GetDefaultGuiFont(LOGFONTW *log_font) {
    if (log_font == NULL) {
      return false;
    }

    CLogFont message_box_font;
    // Use message box font as a default font to be consistent with
    // the candidate window.
    // TODO(yukawa): make a theme layer which is responsible for
    //   the look and feel of both composition window and candidate window.
    // TODO(yukawa): verify the font can render U+005C as a yen sign.
    //               (http://b/1992773)
    message_box_font.SetMessageBoxFont();
    // Use factor "3" to be consistent with the candidate window.
    message_box_font.MakeLarger(3);
    message_box_font.lfWeight = FW_NORMAL;

    *log_font = message_box_font;
    return true;
  }
};

class NativeWorkingAreaAPI : public WorkingAreaInterface {
 public:
  NativeWorkingAreaAPI() {}

 private:
  virtual bool GetWorkingAreaFromPoint(const POINT &point,
                                       RECT *working_area) {
    if (working_area == nullptr) {
      return false;
    }
    ::SetRect(working_area, 0, 0, 0, 0);

    // Obtain the monitor's working area
    const HMONITOR monitor = ::MonitorFromPoint(point,
                                                MONITOR_DEFAULTTONEAREST);
    if (monitor == nullptr) {
      return false;
    }

    MONITORINFO monitor_info = {};
    monitor_info.cbSize = CCSIZEOF_STRUCT(MONITORINFO, dwFlags);
    if (!::GetMonitorInfo(monitor, &monitor_info)) {
      const DWORD error = GetLastError();
      LOG(ERROR) << "GetMonitorInfo failed. Error: " << error;
      return false;
    }

    *working_area = monitor_info.rcWork;
    return true;
  }
};

class NativeWindowPositionAPI : public WindowPositionInterface {
 public:
  NativeWindowPositionAPI()
    : logical_to_physical_point_(GetLogicalToPhysicalPoint()) {
  }

  virtual ~NativeWindowPositionAPI() {}

  virtual bool LogicalToPhysicalPoint(
      HWND window_handle, const POINT &logical_coordinate,
      POINT *physical_coordinate) {
    if (physical_coordinate == NULL) {
      return false;
    }
    DCHECK_NE(NULL, physical_coordinate);
    if (!::IsWindow(window_handle)) {
      return false;
    }
    if (logical_to_physical_point_ == NULL) {
      // In Windows XP, LogicalToPhysicalPoint API is not available.
      // In this case, we simply returns the specified coordinate and returns
      // true.
      *physical_coordinate = logical_coordinate;
      return true;
    }
    // The attached window is likely to be a child window but only root
    // windows are fully supported by LogicalToPhysicalPoint API.  Using
    // root window handle instead of target window handle is likely to make
    // this API happy.
    const HWND root_window_handle = GetRootWindow(window_handle);

    // The document of LogicalToPhysicalPoint API is somewhat ambiguous.
    // http://msdn.microsoft.com/en-us/library/ms633533.aspx
    // Both input coordinates and output coordinates of this API are so-called
    // screen coordinates (offset from the upper-left corner of the screen).
    // Note that the input coordinates are logical coordinates, which means you
    // should pass screen coordinates obtained in a DPI-unaware process to
    // this API.  For example, coordinates returned by ClientToScreen API in a
    // DPI-unaware process are logical coordinates.  You can copy these
    // coordinates to a DPI-aware process and convert them to physical screen
    // coordinates by LogicalToPhysicalPoint API.
    *physical_coordinate = logical_coordinate;
    return logical_to_physical_point_(root_window_handle,
                                      physical_coordinate) != FALSE;
  }

  // This method is not const to implement Win32WindowInterface.
  virtual bool GetWindowRect(HWND window_handle, RECT *rect) {
    return (::GetWindowRect(window_handle, rect) != FALSE);
  }

  // This method is not const to implement Win32WindowInterface.
  virtual bool GetClientRect(HWND window_handle, RECT *rect) {
    return (::GetClientRect(window_handle, rect) != FALSE);
  }

  // This method is not const to implement Win32WindowInterface.
  virtual bool ClientToScreen(HWND window_handle, POINT *point) {
    return (::ClientToScreen(window_handle, point) != FALSE);
  }

  // This method is not const to implement Win32WindowInterface.
  virtual bool IsWindow(HWND window_handle) {
    return (::IsWindow(window_handle) != FALSE);
  }

  // This method is not const to implement Win32WindowInterface.
  virtual HWND GetRootWindow(HWND window_handle) {
    // See the following document for Win32 window system.
    // http://msdn.microsoft.com/en-us/library/ms997562.aspx
    return ::GetAncestor(window_handle, GA_ROOT);
  }

  // This method is not const to implement Win32WindowInterface.
  virtual bool GetWindowClassName(HWND window_handle, wstring *class_name) {
    if (class_name == NULL) {
      return false;
    }
    wchar_t class_name_buffer[1024] = {};
    const size_t num_copied_without_null = ::GetClassNameW(
        window_handle, class_name_buffer, ARRAYSIZE(class_name_buffer));
    if (num_copied_without_null >= (ARRAYSIZE(class_name_buffer) - 1)) {
      DLOG(ERROR) << "buffer length is insufficient.";
      return false;
    }
    class_name_buffer[num_copied_without_null] = L'\0';
    class_name->assign(class_name_buffer);
    return (::IsWindow(window_handle) != FALSE);
  }

 private:
  typedef BOOL (WINAPI *FPLogicalToPhysicalPoint)(HWND window_handle,
                                                  POINT *point);
  static FPLogicalToPhysicalPoint GetLogicalToPhysicalPoint() {
    // LogicalToPhysicalPoint API is available in Vista or later.
    const HMODULE module = WinUtil::GetSystemModuleHandle(L"user32.dll");
    if (module == nullptr) {
      return nullptr;
    }
    // Despite its name, LogicalToPhysicalPoint API no longer converts
    // coordinates on Windows 8.1 and later. We must use
    // LogicalToPhysicalPointForPerMonitorDPI API instead when it is available.
    // See http://go.microsoft.com/fwlink/?LinkID=307061
    void *function = ::GetProcAddress(
        module, "LogicalToPhysicalPointForPerMonitorDPI");
    if (function == nullptr) {
      // When LogicalToPhysicalPointForPerMonitorDPI API does not exist but
      // LogicalToPhysicalPoint API exists, LogicalToPhysicalPoint works fine.
      // This is the case on Windows Vista, Windows 7 and Windows 8.
      function = ::GetProcAddress(module, "LogicalToPhysicalPoint");
      if (function == nullptr) {
        return nullptr;
      }
    }
    return reinterpret_cast<FPLogicalToPhysicalPoint>(function);
  }

  FPLogicalToPhysicalPoint logical_to_physical_point_;

  DISALLOW_COPY_AND_ASSIGN(NativeWindowPositionAPI);
};

struct WindowInfo {
  wstring class_name;
  CRect window_rect;
  CPoint client_area_offset;
  CSize client_area_size;
  double scale_factor;
  WindowInfo()
      : scale_factor(1.0) {}
};

class SystemPreferenceEmulatorImpl : public SystemPreferenceInterface {
 public:
  explicit SystemPreferenceEmulatorImpl(const LOGFONTW &gui_font)
      : default_gui_font_(gui_font) {}

  virtual ~SystemPreferenceEmulatorImpl() {}

  virtual bool GetDefaultGuiFont(LOGFONTW *log_font) {
    if (log_font == NULL) {
      return false;
    }
    *log_font = default_gui_font_;
    return true;
  }

 private:
  CLogFont default_gui_font_;
};

class WorkingAreaEmulatorImpl : public WorkingAreaInterface {
 public:
  explicit WorkingAreaEmulatorImpl(const CRect &area)
      : area_(area) {}

 private:
  virtual bool GetWorkingAreaFromPoint(const POINT &point,
                                       RECT *working_area) {
    if (working_area == nullptr) {
      return false;
    }
    *working_area = area_;
    return true;
  }
  const CRect area_;
};

class WindowPositionEmulatorImpl : public WindowPositionEmulator {
 public:
  WindowPositionEmulatorImpl() {}
  virtual ~WindowPositionEmulatorImpl() {}

  // This method is not const to implement Win32WindowInterface.
  virtual bool GetWindowRect(HWND window_handle, RECT *rect) {
    if (rect == NULL) {
      return false;
    }
    const WindowInfo *info = GetWindowInfomation(window_handle);
    if (info == NULL) {
      return false;
    }
    *rect = info->window_rect;
    return true;
  }

  // This method is not const to implement Win32WindowInterface.
  virtual bool GetClientRect(HWND window_handle, RECT *rect) {
    if (rect == NULL) {
      return false;
    }
    const WindowInfo *info = GetWindowInfomation(window_handle);
    if (info == NULL) {
      return false;
    }
    *rect = CRect(CPoint(0, 0), info->client_area_size);
    return true;
  }

  // This method is not const to implement Win32WindowInterface.
  virtual bool ClientToScreen(HWND window_handle, POINT *point) {
    if (point == NULL) {
      return false;
    }
    const WindowInfo *info = GetWindowInfomation(window_handle);
    if (info == NULL) {
      return false;
    }
    *point = (info->window_rect.TopLeft() + info->client_area_offset +
              *point);
    return true;
  }

  // This method is not const to implement Win32WindowInterface.
  virtual bool IsWindow(HWND window_handle) {
    const WindowInfo *info = GetWindowInfomation(window_handle);
    if (info == NULL) {
      return false;
    }
    return true;
  }

  // This method wraps API call of GetAncestor/GA_ROOT.
  virtual HWND GetRootWindow(HWND window_handle) {
    const map<HWND, HWND>::const_iterator it = root_map_.find(window_handle);
    if (it == root_map_.end()) {
      return window_handle;
    }
    return it->second;
  }

  // This method is not const to implement Win32WindowInterface.
  virtual bool GetWindowClassName(HWND window_handle, wstring *class_name) {
    if (class_name == NULL) {
      return false;
    }
    const WindowInfo *info = GetWindowInfomation(window_handle);
    if (info == NULL) {
      return false;
    }
    *class_name = info->class_name;
    return true;
  }

  // This method is not const to implement Win32WindowInterface.
  virtual bool LogicalToPhysicalPoint(
      HWND window_handle, const POINT &logical_coordinate,
      POINT *physical_coordinate) {
    if (physical_coordinate == NULL) {
      return false;
    }

    DCHECK_NE(NULL, physical_coordinate);
    const WindowInfo *root_info =
        GetWindowInfomation(GetRootWindow(window_handle));
    if (root_info == NULL) {
      return false;
    }

    // BottomRight is treated inside of the rect in this scenario.
    const CRect &bottom_right_inflated_rect = CRect(
        root_info->window_rect.left,
        root_info->window_rect.top,
        root_info->window_rect.right + 1,
        root_info->window_rect.bottom + 1);
    if (bottom_right_inflated_rect.PtInRect(logical_coordinate) == FALSE) {
      return false;
    }
    physical_coordinate->x = logical_coordinate.x * root_info->scale_factor;
    physical_coordinate->y = logical_coordinate.y * root_info->scale_factor;
    return true;
  }

  virtual HWND RegisterWindow(
      const wstring &class_name, const RECT &window_rect,
      const POINT &client_area_offset, const SIZE &client_area_size,
      double scale_factor) {
    const HWND hwnd = GetNextWindowHandle();
    window_map_[hwnd].class_name = class_name;
    window_map_[hwnd].window_rect = window_rect;
    window_map_[hwnd].client_area_offset = client_area_offset;
    window_map_[hwnd].client_area_size = client_area_size;
    window_map_[hwnd].scale_factor = scale_factor;
    return hwnd;
  }

  virtual void SetRoot(HWND child_window, HWND root_window) {
    root_map_[child_window] = root_window;
  }

 private:
  HWND GetNextWindowHandle() const {
    if (window_map_.size() > 0) {
      const HWND last_hwnd = window_map_.rbegin()->first;
      return reinterpret_cast<HWND>(
          reinterpret_cast<BYTE *>(last_hwnd) + sizeof(last_hwnd));
    }
    return reinterpret_cast<HWND>(0x12345678);
  }

  // This method is not const to implement Win32WindowInterface.
  const WindowInfo *GetWindowInfomation(HWND hwnd) {
    if (window_map_.find(hwnd) == window_map_.end()) {
      return NULL;
    }
    return &(window_map_.find(hwnd)->second);
  }

  map<HWND, WindowInfo> window_map_;
  map<HWND, HWND> root_map_;

  DISALLOW_COPY_AND_ASSIGN(WindowPositionEmulatorImpl);
};

bool IsVerticalWriting(const CandidateWindowLayoutParams &params) {
  return params.vertical_writing.has_value() &&
         params.vertical_writing.value();
}

// This is a helper function for LayoutCandidateWindowByCandidateForm.
// Some applications give us only the base position of candidate window.
// However, the exclude region is definitely important in terms of UX around
// candidate/suggest window.  As a workaround, we try to use font height to
// compose a virtual exclude region from the base position.
//   Expected applications and controls are:
//     - Candidate Window on Pidgin 2.6.1
//     - Candidate Window on V2C 2.1.6 on JRE 1.6.0.21
//     - Candidate Window on Fudemame 21
//   See also relevant unit tests.
// Returns true if the |candidate_layout| is determined in successful.
bool UpdateCandidateWindowFromBasePosAndFontHeight(
    const CandidateWindowLayoutParams &params,
    int compatibility_mode,
    const CPoint &base_pos_in_logical_coord,
    LayoutManager *layout_manager,
    CandidateWindowLayout *candidate_layout) {
  DCHECK(candidate_layout);
  candidate_layout->Clear();

  if (!params.window_handle.has_value()) {
    return false;
  }
  const HWND target_window = params.window_handle.value();

  const int font_height = GetAbsoluteFontHeight(params);
  if (font_height == 0) {
    return false;
  }
  DCHECK_LT(0, font_height);

  const bool is_vertical = IsVerticalWriting(params);
  CRect exclude_region_in_logical_coord;
  if (is_vertical) {
    // Vertical
    exclude_region_in_logical_coord.SetRect(
        base_pos_in_logical_coord.x,
        base_pos_in_logical_coord.y,
        base_pos_in_logical_coord.x + font_height,
        base_pos_in_logical_coord.y + 1);
  } else {
    // Horizontal
    exclude_region_in_logical_coord.SetRect(
        base_pos_in_logical_coord.x,
        base_pos_in_logical_coord.y - font_height,
        base_pos_in_logical_coord.x + 1,
        base_pos_in_logical_coord.y);
  }

  CRect exclude_region_in_physical_coord;
  layout_manager->GetRectInPhysicalCoords(
      target_window, exclude_region_in_logical_coord,
      &exclude_region_in_physical_coord);

  const CPoint base_pos_in_physical_coord =
      GetBasePositionFromExcludeRect(exclude_region_in_physical_coord,
                                     is_vertical);
  candidate_layout->InitializeWithPositionAndExcludeRegion(
      base_pos_in_physical_coord, exclude_region_in_physical_coord);
  return true;
}

// CANDIDATEFORM is most standard way to specify the position of a candidate
// window.  There are two major cases; one has an exclude region and the other
// has no exclude region.  The second case is virtually handled by
// UpdateCandidateWindowFromBasePosAndFontHeight function.
//   Expected applications and controls (for the first case) are:
//     - Suggest Window on apps with CAN_USE_CANDIDATE_FORM_FOR_SUGGEST
//     -- Qt-related windows whose class name is "QWidget"
//     -- Google Chrome-related windows whose class name is
//        "Chrome_RenderWidgetHostHWND"
//     - Candidate Window on windows which do not support IMECHARPOSITION
//     -- Internet Explorer
//     -- Open Office Writer
//     -- Qt-based applications
//   See also relevant unit tests.
// Returns true if the |candidate_layout| is determined in successful.
bool LayoutCandidateWindowByCandidateForm(
    const CandidateWindowLayoutParams &params,
    int compatibility_mode,
    LayoutManager *layout_manager,
    CandidateWindowLayout *candidate_layout) {
  DCHECK(candidate_layout);
  candidate_layout->Clear();

  if (!params.window_handle.has_value()) {
    return false;
  }
  if (!params.candidate_form.has_value()) {
    return false;
  }

  const HWND target_window = params.window_handle.value();
  const CandidateWindowLayout &form = params.candidate_form.value();

  CPoint base_pos_in_physical_coord;
  layout_manager->GetPointInPhysicalCoords(
      target_window, form.position(), &base_pos_in_physical_coord);

  if (!form.has_exclude_region()) {
    // If the candidate form does not have the exclude region, try to compose
    // supplemental exclude region by using font height information.
    CandidateWindowLayout layout;
    if (UpdateCandidateWindowFromBasePosAndFontHeight(
            params, compatibility_mode, form.position(), layout_manager,
            &layout)) {
      // succeeded to compose exclude region.
      DCHECK(layout.initialized());
      *candidate_layout = layout;
      return true;
    }
    candidate_layout->InitializeWithPosition(base_pos_in_physical_coord);
    return true;
  }

  DCHECK(form.has_exclude_region());

  CRect exclude_region_in_physical_coord;
  layout_manager->GetRectInPhysicalCoords(
      target_window, form.exclude_region(),
      &exclude_region_in_physical_coord);

  candidate_layout->InitializeWithPositionAndExcludeRegion(
      base_pos_in_physical_coord, exclude_region_in_physical_coord);
  return true;
}

// This function tries to use IMECHARPOSITION structure, which gives us
// sufficient information around the focused segment to use EXCLUDE-style
// positioning.  However, relatively small number of applications support
// this structure.
//   Expected applications and controls are:
//     - Microsoft Word
//     - Built-in RichEdit control
//     -- Chrome's Omni-box
//     - Built-in Edit control
//     -- Internet Explorer's address bar
//     - Firefox
//   See also relevant unit tests.
// Returns true if the |candidate_layout| is determined in successful.
bool LayoutCandidateWindowByCompositionTarget(
    const CandidateWindowLayoutParams &params,
    int compatibility_mode,
    LayoutManager *layout_manager,
    CandidateWindowLayout *candidate_layout) {
  DCHECK(candidate_layout);
  candidate_layout->Clear();

  if (!params.window_handle.has_value()) {
    return false;
  }
  if (!params.char_pos.has_value()) {
    return false;
  }

  const HWND target_window = params.window_handle.value();
  const IMECHARPOSITION &char_pos = params.char_pos.value();

  // From the behavior of MS Office, we assume that an application fills
  // members in IMECHARPOSITION as follows, even though other interpretations
  // might be possible from the document especially for the vertical writing.
  //   http://msdn.microsoft.com/en-us/library/dd318162.aspx
  //
  // [Horizontal Writing]
  //
  //    (pt)
  //     v_____
  //     |     |
  //     |     | (cLineHeight)
  //     |     |
  //   --+-----+---------->  (Base Line)
  //
  // [Vertical Writing]
  //
  //    |
  //    +-----< (pt)
  //    |     |
  //    |-----+
  //    | (cLineHeight)
  //    |
  //    |
  //    v
  //   (Base Line)

  const bool is_vertical = IsVerticalWriting(params);
  CRect exclude_region_in_logical_coord;
  if (is_vertical) {
    // Vertical
    exclude_region_in_logical_coord.left =
        char_pos.pt.x - char_pos.cLineHeight;
    exclude_region_in_logical_coord.top = char_pos.pt.y;
    exclude_region_in_logical_coord.right = char_pos.pt.x;
    exclude_region_in_logical_coord.bottom = char_pos.pt.y + 1;
  } else {
    // Horizontal
    exclude_region_in_logical_coord.left = char_pos.pt.x;
    exclude_region_in_logical_coord.top = char_pos.pt.y;
    exclude_region_in_logical_coord.right = char_pos.pt.x + 1;
    exclude_region_in_logical_coord.bottom =
        char_pos.pt.y + char_pos.cLineHeight;
  }

  const CPoint base_pos_in_logical_coord =
      GetBasePositionFromExcludeRect(exclude_region_in_logical_coord,
                                     is_vertical);

  CPoint base_pos_in_physical_coord;
  layout_manager->GetPointInPhysicalCoords(
      target_window, base_pos_in_logical_coord,
      &base_pos_in_physical_coord);

  CRect exclude_region_in_physical_coord;
  layout_manager->GetRectInPhysicalCoords(
      target_window, exclude_region_in_logical_coord,
      &exclude_region_in_physical_coord);

  candidate_layout->InitializeWithPositionAndExcludeRegion(
      base_pos_in_physical_coord, exclude_region_in_physical_coord);
  return true;
}

// COMPOSITIONFORM contains the expected position of top-left corner of the
// composition window, which might be used to determine the position of the
// candidate window if no other relevant information is available.
// Actually the top left corner might be good enough for vertical writing.
// As for horizontal writing, the base position can be calculated if the height
// of the composition string is available.  This function supposes that the
// font height approximates to the height of the composition string.
// In both cases, this function also tries to compose an exclude region to
// improve the UX around suggest/candidate window if font height is available.
//   Expected applications and controls are:
//     - Suggest window on Pidgin 2.6.1
//   See also relevant unit tests.
// Returns true if the |candidate_layout| is determined in successful.
bool LayoutCandidateWindowByCompositionForm(
    const CandidateWindowLayoutParams &params,
    int compatibility_mode,
    LayoutManager *layout_manager,
    CandidateWindowLayout *candidate_layout) {
  DCHECK(candidate_layout);
  candidate_layout->Clear();

  if (!params.window_handle.has_value()) {
    return false;
  }
  if (!params.composition_form_topleft.has_value()) {
    return false;
  }

  const HWND target_window = params.window_handle.value();
  const CPoint &topleft_in_logical_coord =
      params.composition_form_topleft.value();
  const bool is_vertical = IsVerticalWriting(params);
  const int font_height = GetAbsoluteFontHeight(params);

  if (!is_vertical) {
    // For horizontal writing, a valid |font_height| is necessary to calculate
    // an appropriate position of suggest/candidate window.
    if (font_height == 0) {
      return false;
    }
    DCHECK_LT(0, font_height);

    const CRect rect_in_logical_coord(
        topleft_in_logical_coord.x,
        topleft_in_logical_coord.y,
        topleft_in_logical_coord.x + 1,
        topleft_in_logical_coord.y + font_height);

    CRect rect_in_physical_coord;
    layout_manager->GetRectInPhysicalCoords(
        target_window, rect_in_logical_coord, &rect_in_physical_coord);

    const CPoint bottom_left_in_physical_coord(
        rect_in_physical_coord.left, rect_in_physical_coord.bottom);
    candidate_layout->InitializeWithPositionAndExcludeRegion(
        bottom_left_in_physical_coord, rect_in_physical_coord);
    return true;
  }

  // Vertical
  DCHECK(is_vertical);
  CPoint topleft_in_physical_coord;
  layout_manager->GetPointInPhysicalCoords(
      target_window, topleft_in_logical_coord,
      &topleft_in_physical_coord);

  if (font_height == 0) {
    // For vertical writing, top-left cornier is acceptable.
    // Use CANDIDATEPOS-style by compromise.
    candidate_layout->InitializeWithPosition(topleft_in_physical_coord);
    return true;
  }
  DCHECK_LT(0, font_height);

  const CRect rect_in_logical_coord(
      topleft_in_logical_coord.x,
      topleft_in_logical_coord.y,
      topleft_in_logical_coord.x + font_height,
      topleft_in_logical_coord.y + 1);

  CRect rect_in_physical_coord;
  layout_manager->GetRectInPhysicalCoords(
      target_window, rect_in_logical_coord, &rect_in_physical_coord);

  candidate_layout->InitializeWithPositionAndExcludeRegion(
      topleft_in_physical_coord, rect_in_physical_coord);
  return true;
}

// This function calculates the candidate window position by using caret
// information, which is generally unreliable but sometimes becomes a good
// alternative even when no other positional information is available.
// In fact, the position of suggest window sometimes relies on the caret
// position because it is not guaranteed that the CANDIDATEFORM is valid before
// the application receives IMN_OPENCANDIDATE message.
// Another important consideration is how to calculate the exclude region.
// One may consider that the caret rect seems to be used but very small number
// of applications always use 1x1 rect regardless of the actual caret size.
// To improve the positional accuracy of the exclude region, this function
// adopt larger one between the caret height and font height when the exclude
// region is calculated.
//   Relevant applications and controls are:
//     - Workaround against Google Chrome (b/3104035)
//     - Suggest window on Hidemaru
//     - Suggest window on Open Office Writer
//     - Suggest window on Internet Explorer 8
//   See also relevant unit tests.
// Returns true if the |candidate_layout| is determined in successful.
bool LayoutCandidateWindowByCaretInfo(
    const CandidateWindowLayoutParams &params,
    int compatibility_mode,
    LayoutManager *layout_manager,
    CandidateWindowLayout *candidate_layout) {
  DCHECK(candidate_layout);
  candidate_layout->Clear();

  if (!params.window_handle.has_value()) {
    return false;
  }
  if (!params.caret_rect.has_value()) {
    return false;
  }

  const HWND target_window = params.window_handle.value();
  CRect exclude_region_in_logical_coord = params.caret_rect.value();

  // Use font height if available to improve the accuracy of exclude region.
  const int font_height = GetAbsoluteFontHeight(params);
  const bool is_vertical = IsVerticalWriting(params);

  if (font_height > 0) {
    if (is_vertical &&
        (exclude_region_in_logical_coord.Width() < font_height)) {
      // Vertical
      exclude_region_in_logical_coord.right =
          exclude_region_in_logical_coord.left + font_height;
    } else if (!is_vertical &&
               (exclude_region_in_logical_coord.Height() < font_height)) {
      // Horizontal
      exclude_region_in_logical_coord.bottom =
          exclude_region_in_logical_coord.top + font_height;
    }
  }

  CRect exclude_region_in_physical_coord;
  layout_manager->GetRectInPhysicalCoords(
      target_window, exclude_region_in_logical_coord,
      &exclude_region_in_physical_coord);

  const CPoint base_pos_in_physical_coord =
      GetBasePositionFromExcludeRect(exclude_region_in_physical_coord,
                                     is_vertical);

  candidate_layout->InitializeWithPositionAndExcludeRegion(
      base_pos_in_physical_coord, exclude_region_in_physical_coord);
  return true;
}

// On some applications, no positional information is available especially when
// the client want to show the suggest window.  In this case, we might want to
// show the (suggest) window next to the target window so that the candidate
// window will not cover the target window.
//   Expected applications and controls are:
//     - Suggest window on Fudemame 21
//   See also relevant unit tests.
// Returns true if the |candidate_layout| is determined in successful.
bool LayoutCandidateWindowByClientRect(
    const CandidateWindowLayoutParams &params,
    int compatibility_mode,
    LayoutManager *layout_manager,
    CandidateWindowLayout *candidate_layout) {
  DCHECK(candidate_layout);
  candidate_layout->Clear();

  if (!params.window_handle.has_value()) {
    return false;
  }
  if (!params.client_rect.has_value()) {
    return false;
  }

  const HWND target_window = params.window_handle.value();
  const CRect &client_rect_in_logical_coord =
      params.client_rect.value();
  const bool is_vertical = IsVerticalWriting(params);

  CRect client_rect_in_physical_coord;
  layout_manager->GetRectInPhysicalCoords(
      target_window, client_rect_in_logical_coord,
      &client_rect_in_physical_coord);

  if (is_vertical) {
    // Vertical
    // Current candidate window has not fully supported vertical writing yet so
    // it would be rather better to show the candidate window at the right side
    // of the target window.
    // This is why we do not use GetBasePositionFromExcludeRect here.
    // TODO(yukawa): use GetBasePositionFromExcludeRect once the vertical
    //   writing is fully supported by the candidate window.
    candidate_layout->InitializeWithPosition(CPoint(
        client_rect_in_physical_coord.right,
        client_rect_in_physical_coord.top));
  } else {
    // Horizontal
    candidate_layout->InitializeWithPosition(CPoint(
        client_rect_in_physical_coord.left,
        client_rect_in_physical_coord.bottom));
  }
  return true;
}

bool LayoutIndicatorWindowByCompositionTarget(
    const CandidateWindowLayoutParams &params,
    const LayoutManager &layout_manager,
    CRect *target_rect) {
  DCHECK(target_rect);
  *target_rect = CRect();

  if (!params.window_handle.has_value()) {
    return false;
  }
  if (!params.char_pos.has_value()) {
    return false;
  }

  const HWND target_window = params.window_handle.value();
  const IMECHARPOSITION &char_pos = params.char_pos.value();

  // From the behavior of MS Office, we assume that an application fills
  // members in IMECHARPOSITION as follows, even though other interpretations
  // might be possible from the document especially for the vertical writing.
  //   http://msdn.microsoft.com/en-us/library/dd318162.aspx

  const bool is_vertical = IsVerticalWriting(params);
  CRect rect_in_logical_coord;
  if (is_vertical) {
    // [Vertical Writing]
    //
    //    |
    //    +-----< (pt)
    //    |     |
    //    |-----+
    //    | (cLineHeight)
    //    |
    //    |
    //    v
    //   (Base Line)
    rect_in_logical_coord = CRect(
        char_pos.pt.x - char_pos.cLineHeight,
        char_pos.pt.y,
        char_pos.pt.x,
        char_pos.pt.y + 1);
  } else {
    // [Horizontal Writing]
    //
    //    (pt)
    //     v_____
    //     |     |
    //     |     | (cLineHeight)
    //     |     |
    //   --+-----+---------->  (Base Line)
    rect_in_logical_coord = CRect(
        char_pos.pt.x,
        char_pos.pt.y,
        char_pos.pt.x + 1,
        char_pos.pt.y + char_pos.cLineHeight);
  }

  layout_manager.GetRectInPhysicalCoords(
      target_window, rect_in_logical_coord, target_rect);
  return true;
}

bool LayoutIndicatorWindowByCompositionForm(
    const CandidateWindowLayoutParams &params,
    const LayoutManager &layout_manager,
    CRect *target_rect) {
  DCHECK(target_rect);
  *target_rect = CRect();
  if (!params.window_handle.has_value()) {
    return false;
  }
  if (!params.composition_form_topleft.has_value()) {
    return false;
  }

  const HWND target_window = params.window_handle.value();
  const CPoint &topleft_in_logical_coord =
      params.composition_form_topleft.value();
  const bool is_vertical = IsVerticalWriting(params);
  const int font_height = GetAbsoluteFontHeight(params);
  if (font_height <= 0) {
    return false;
  }

  const CRect rect_in_logical_coord(
      topleft_in_logical_coord,
      is_vertical ? CSize(font_height, 1) : CSize(1, font_height));

  layout_manager.GetRectInPhysicalCoords(
      target_window, rect_in_logical_coord, target_rect);
  return true;
}

bool LayoutIndicatorWindowByCaretInfo(
    const CandidateWindowLayoutParams &params,
    const LayoutManager &layout_manager,
    CRect *target_rect) {
  DCHECK(target_rect);
  *target_rect = CRect();
  if (!params.window_handle.has_value()) {
    return false;
  }
  if (!params.caret_rect.has_value()) {
    return false;
  }

  const HWND target_window = params.window_handle.value();
  CRect rect_in_logical_coord = params.caret_rect.value();

  // Use font height if available to improve the accuracy of exlude region.
  const int font_height = GetAbsoluteFontHeight(params);
  const bool is_vertical = IsVerticalWriting(params);

  if (font_height > 0) {
    if (is_vertical &&
        (rect_in_logical_coord.Width() < font_height)) {
      // Vertical
      rect_in_logical_coord.right =
          rect_in_logical_coord.left + font_height;
    } else if (!is_vertical &&
               (rect_in_logical_coord.Height() < font_height)) {
      // Horizontal
      rect_in_logical_coord.bottom =
          rect_in_logical_coord.top + font_height;
    }
  }

  layout_manager.GetRectInPhysicalCoords(
      target_window, rect_in_logical_coord, target_rect);
  return true;
}

bool GetTargetRectForIndicator(
    const CandidateWindowLayoutParams &params,
    const LayoutManager &layout_manager,
    CRect *focus_rect) {
  if (focus_rect == nullptr) {
    return false;
  }

  if (LayoutIndicatorWindowByCompositionTarget(params, layout_manager,
                                               focus_rect)) {
    return true;
  }
  if (LayoutIndicatorWindowByCompositionForm(params,
                                             layout_manager,
                                             focus_rect)) {
    return true;
  }
  if (LayoutIndicatorWindowByCaretInfo(params,
                                       layout_manager,
                                       focus_rect)) {
    return true;
  }

  // Clear the data just in case.
  *focus_rect = CRect();
  return false;
}

}  // namespace

SystemPreferenceInterface *SystemPreferenceFactory::CreateMock(
    const LOGFONTW &gui_font) {
  return new SystemPreferenceEmulatorImpl(gui_font);
}

WorkingAreaInterface *WorkingAreaFactory::Create() {
  return new NativeWorkingAreaAPI();
}

WorkingAreaInterface *WorkingAreaFactory::CreateMock(
    const RECT &working_area) {
  return new WorkingAreaEmulatorImpl(working_area);
}

WindowPositionEmulator *WindowPositionEmulator::Create() {
  return new WindowPositionEmulatorImpl();
}

CharacterRange::CharacterRange()
    : begin(0),
      length(0) {}

LineLayout::LineLayout()
    : line_length(0),
      line_width(0),
      line_start_offset(0) {}

CandidateWindowLayout::CandidateWindowLayout()
    : position_(CPoint()),
      exclude_region_(CRect()),
      has_exclude_region_(false),
      initialized_(false) {}

CandidateWindowLayout::~CandidateWindowLayout() {}

void CandidateWindowLayout::Clear() {
  position_ = CPoint();
  exclude_region_ = CRect();
  has_exclude_region_ = false;
  initialized_ = false;
}

void CandidateWindowLayout::InitializeWithPosition(const POINT &position) {
  position_ = position;
  exclude_region_ = CRect();
  has_exclude_region_ = false;
  initialized_ = true;
}

void CandidateWindowLayout::InitializeWithPositionAndExcludeRegion(
    const POINT &position, const RECT &exclude_region) {
  position_ = position;
  exclude_region_ = exclude_region;
  has_exclude_region_ = true;
  initialized_ = true;
}

const POINT &CandidateWindowLayout::position() const {
  return position_;
}

const RECT &CandidateWindowLayout::exclude_region() const {
  DCHECK(has_exclude_region_);
  return exclude_region_;
}

bool CandidateWindowLayout::has_exclude_region() const {
  return has_exclude_region_;
}

bool CandidateWindowLayout::initialized() const {
  return initialized_;
}

IndicatorWindowLayout::IndicatorWindowLayout()
    : is_vertical(false) {
  ::SetRect(&window_rect, 0, 0, 0, 0);
}

void IndicatorWindowLayout::Clear() {
  is_vertical = false;
  ::SetRect(&window_rect, 0, 0, 0, 0);
}

bool LayoutManager::CalcLayoutWithTextWrapping(
    const LOGFONTW &font,
    const wstring &text,
    int maximum_line_length,
    int initial_offset,
    vector<LineLayout> *line_layouts) {
  if (line_layouts == NULL) {
    return false;
  }
  line_layouts->clear();

  CFont new_font(CLogFont(font).CreateFontIndirectW());
  if (new_font.IsNull()) {
    LOG(ERROR) << "CreateFont failed.";
    return false;
  }

  CDC dc;
  // Create a memory DC compatible with desktop DC.
  dc.CreateCompatibleDC(CDC(::GetDC(NULL)));
  CFontHandle old_font = dc.SelectFont(new_font);

  const bool result = CalcLayoutWithTextWrappingInternal(
      dc.m_hDC, text, maximum_line_length, initial_offset,
      line_layouts);
  dc.SelectFont(old_font);

  return result;
}

void LayoutManager::GetPointInPhysicalCoords(
    HWND window_handle, const POINT &point, POINT *result) const {
  if (result == NULL) {
    return;
  }

  DCHECK_NE(nullptr, window_position_.get());
  if (window_position_->LogicalToPhysicalPoint(
          window_handle, point, result)) {
    return;
  }

  // LogicalToPhysicalPoint API failed for some reason.
  // Emulate the result based on the scaling factor.
  const HWND root_window_handle =
      window_position_->GetRootWindow(window_handle);
  const double scale_factor = GetScalingFactor(root_window_handle);
  result->x = point.x * scale_factor;
  result->y = point.y * scale_factor;
  return;
}

void LayoutManager::GetRectInPhysicalCoords(
    HWND window_handle, const RECT &rect, RECT *result) const {
  if (result == NULL) {
    return;
  }

  DCHECK_NE(nullptr, window_position_.get());

  CPoint top_left;
  GetPointInPhysicalCoords(
      window_handle, CPoint(rect.left, rect.top), &top_left);
  CPoint bottom_right;
  GetPointInPhysicalCoords(
      window_handle, CPoint(rect.right, rect.bottom), &bottom_right);
  *result = CRect(top_left, bottom_right);
  return;
}

SegmentMarkerLayout::SegmentMarkerLayout()
    : from(CPoint()),
      to(CPoint()),
      highlighted(false) {}

CompositionWindowLayout::CompositionWindowLayout()
    : window_position_in_screen_coordinate(CRect()),
      caret_rect(CRect()),
      text_area(CRect()),
      base_position(CPoint()),
      log_font(CLogFont()) {}

LayoutManager::LayoutManager()
    : system_preference_(new NativeSystemPreferenceAPI),
      window_position_(new NativeWindowPositionAPI) {}

LayoutManager::LayoutManager(SystemPreferenceInterface *mock_system_preference,
                             WindowPositionInterface *mock_window_position)
    : system_preference_(mock_system_preference),
      window_position_(mock_window_position) {}

LayoutManager::~LayoutManager() {}

// TODO(yukawa): Refactor this function into smaller functions as soon as
//   possible so that you can update the functionality and add new unit tests
//   more easily.
bool LayoutManager::LayoutCompositionWindow(
    const commands::RendererCommand &command,
    vector<CompositionWindowLayout> *composition_window_layouts,
    CandidateWindowLayout *candidate_layout) const {
  if (composition_window_layouts != NULL) {
    composition_window_layouts->clear();
  }
  if (candidate_layout != NULL) {
    candidate_layout->Clear();
  }

  if (!command.has_output() ||
      !command.output().has_preedit() ||
      command.output().preedit().segment_size() <= 0 ||
      !command.output().preedit().has_cursor() ||
      !command.has_application_info() ||
      !command.application_info().has_target_window_handle()) {
    LOG(INFO) << "do nothing because of the lack of parameter(s)";
    return true;
  }
  const mozc::commands::Output &output = command.output();
  const HWND target_window_handle = reinterpret_cast<HWND>(
      command.application_info().target_window_handle());

  const mozc::commands::RendererCommand::ApplicationInfo &app =
      command.application_info();
  CLogFont logfont;
  if (!app.has_composition_font() ||
      !mozc::win32::FontUtil::ToLOGFONT(app.composition_font(), &logfont)) {
    // If the composition font is not available, use default GUI font as a
    // fall back.
    if (!system_preference_->GetDefaultGuiFont(&logfont)) {
      LOG(ERROR) << "GetDefaultGuiFont failed.";
      return false;
    }
  }

  // Remove underline attribute.  See b/2935480 for details.
  logfont.lfUnderline = 0;

  // We only support lfEscapement == 0 or 2700.
  if (logfont.lfEscapement != 0 && logfont.lfEscapement != 2700) {
    LOG(ERROR) << "Unsupported escapement: " << logfont.lfEscapement;
    return false;
  }

  const mozc::commands::Preedit &preedit = output.preedit();

  const bool is_vertical = (GetWritingDirection(app) == VERTICAL_WRITING);

  CompositionForm composition_form;
  if (command.application_info().has_composition_form()) {
    composition_form.CopyFrom(command.application_info().composition_form());
  } else {
    // No composition form is available.  Use client rect instead.
    CRect client_rect;
    if (!window_position_->GetClientRect(target_window_handle, &client_rect)) {
      return false;
    }
    // We need not to use CompositionForm::RECT.  The client area will be used
    // for character wrapping anyway.
    composition_form.set_style_bits(CompositionForm::POINT);
    if (is_vertical) {
      composition_form.mutable_current_position()->set_x(client_rect.left);
      composition_form.mutable_current_position()->set_y(client_rect.top);
    } else {
      composition_form.mutable_current_position()->set_x(client_rect.left);
      composition_form.mutable_current_position()->set_y(client_rect.bottom);
    }
  }

  // TODO(yukawa): Stop supporting |deprecated_style()|.
  const uint32 style_bits =
      (composition_form.has_deprecated_style()
          ? composition_form.deprecated_style()
          : composition_form.style_bits());

  // Check the availability of optional fields.
  // Note that currently we always use |current_position| field even when
  // |style_bits| does not contain CompositionForm::POINT bit.
  if (!composition_form.has_current_position() ||
      !composition_form.current_position().has_x() ||
      !composition_form.current_position().has_y()) {
    return false;
  }

  const HWND root_window_handle =
      window_position_->GetRootWindow(target_window_handle);
  if (root_window_handle == NULL) {
    LOG(ERROR) << "GetRootWindow failed.";
    return false;
  }

  const double scale = GetScalingFactor(root_window_handle);
  const bool no_dpi_virtualization = (scale == 1.0);

  const CPoint current_pos_in_client_coord(
      composition_form.current_position().x(),
      composition_form.current_position().y());

  CPoint current_pos_in_logical_coord;
  if (!ClientPointToScreen(target_window_handle, current_pos_in_client_coord,
                           &current_pos_in_logical_coord)) {
    LOG(ERROR) << "ClientPointToScreen failed.";
    return false;
  }

  CPoint current_pos;
  GetPointInPhysicalCoords(target_window_handle,
                           current_pos_in_logical_coord, &current_pos);

  // Check the availability of optional fields.
  // Note that some applications may set |CompositionForm::RECT| and other
  // style bits like |CompositionForm::POINT| at the same time.
  // See b/3200425 for details.
  bool use_area_in_composition_form = false;
  if (((style_bits & CompositionForm::RECT) == CompositionForm::RECT) &&
      composition_form.has_area() &&
      composition_form.area().has_left() &&
      composition_form.area().has_top() &&
      composition_form.area().has_right() &&
      composition_form.area().has_bottom()) {
    use_area_in_composition_form = true;
  }

  CRect area_in_client_coord;
  if (use_area_in_composition_form) {
    area_in_client_coord.SetRect(
        composition_form.area().left(),
        composition_form.area().top(),
        composition_form.area().right(),
        composition_form.area().bottom());
  } else {
    if (window_position_->GetClientRect(
            target_window_handle, &area_in_client_coord) == FALSE) {
      const int error = ::GetLastError();
      DLOG(ERROR) << "GetClientRect failed.  error = " << error;
      return false;
    }
  }

  CRect area_in_logical_coord;
  if (!ClientRectToScreen(target_window_handle, area_in_client_coord,
                          &area_in_logical_coord)) {
    return false;
  }

  CPoint current_pos_in_physical_coord;
  GetPointInPhysicalCoords(
      target_window_handle, current_pos_in_logical_coord,
      &current_pos_in_physical_coord);

  CRect area_in_physical_coord;
  GetRectInPhysicalCoords(
      target_window_handle, area_in_logical_coord,
      &area_in_physical_coord);

  // Adjust the font size to be equal to that in the target process with
  // taking DPI virtualization into account.
  if (!no_dpi_virtualization) {
    logfont.lfHeight = static_cast<int>(logfont.lfHeight * scale);
  }

  // Ensure the escapement and orientation are consistent with writing
  // direction.  Note that some applications always set 0 to |lfOrientation|.
  if (is_vertical) {
    logfont.lfEscapement = 2700;
    logfont.lfOrientation = 2700;
  } else {
    logfont.lfEscapement = 0;
    logfont.lfOrientation = 0;
  }

  string preedit_utf8;
  vector<int> segment_indices;
  vector<CharacterRange> segment_lengths;
  const wstring composition_text = ComposePreeditText(
      preedit, &preedit_utf8, &segment_indices, &segment_lengths);
  DCHECK_EQ(composition_text.size(), segment_indices.size());
  DCHECK_EQ(preedit.segment_size(), segment_lengths.size());
  vector<mozc::renderer::win32::LineLayout> layouts;
  bool result = false;
  {
    const int offset = is_vertical
        ? current_pos_in_physical_coord.y - area_in_physical_coord.top
        : current_pos_in_physical_coord.x - area_in_physical_coord.left;
    const int limit = is_vertical ? area_in_physical_coord.Height()
                                  : area_in_physical_coord.Width();
    result = CalcLayoutWithTextWrapping(
        logfont, composition_text, limit, offset, &layouts);
  }
  if (!result) {
    LOG(ERROR) << "CalcLayoutWithTextWrapping failed.";
    return false;
  }

  if (composition_window_layouts != NULL) {
    composition_window_layouts->clear();
  }

  int cursor_index = -1;
  if (output.has_candidates() && output.candidates().has_position()) {
    // |cursor_index| is supposed to be wide character index but
    // |output.candidates().position()| is the number of Unicode characters.
    // In case surrogate pair appears, use Util::WideCharsLen to calculate the
    // cursor position as wide character index. See b/4163234 for details.
    cursor_index = Util::WideCharsLen(
        Util::SubString(preedit_utf8, 0, output.candidates().position()));
  }

  const bool is_suggest =
      output.candidates().has_category() &&
      (output.candidates().category() ==  commands::SUGGESTION);

  // When this flag is true, suggest window must not hide preedit text.
  // TODO(yukawa): remove |!is_vertical| when vertical candidate window is
  //   implemented.
  const bool suggest_window_never_hides_preedit = (!is_vertical && is_suggest);

  int total_line_offset = 0;
  int total_characters = 0;
  for (size_t layout_index = 0; layout_index < layouts.size();
       ++layout_index) {
    const mozc::renderer::win32::LineLayout &layout = layouts[layout_index];
    if (layout.text.size() < 0 ||
        layout.line_length < 0 ||
        layout.character_positions.size() < 0) {
      // unexpected values found.
      return false;
    }

    if (layout.text.size() == 0 ||
        layout.line_length == 0 ||
        layout.character_positions.size() == 0) {
      // This line is full.  Go to next line.
      total_line_offset += layout.line_width;
      total_characters += layout.text.size();
      continue;
    }

    DCHECK_GT(layout.text.size(), 0);
    DCHECK_GT(layout.line_length, 0);
    DCHECK_GT(layout.character_positions.size(), 0);

    CompositionWindowLayout window_layout;
    window_layout.text = layout.text;
    window_layout.log_font = logfont;
    CRect window_rect;
    CRect text_rect;
    CPoint base_point;
    if (is_vertical) {
      window_rect.top = area_in_physical_coord.top + layout.line_start_offset;
      window_rect.right = current_pos.x - total_line_offset;
      window_rect.left =
          window_rect.right - layout.line_width;
      window_rect.bottom =
          window_rect.top + layout.line_length;
      text_rect.SetRect(0, 0, layout.line_width, layout.line_length);
      base_point.SetPoint(layout.line_width, 0);
    } else {
      window_rect.left =
          area_in_physical_coord.left + layout.line_start_offset;
      window_rect.top = current_pos.y + total_line_offset;
      window_rect.right = window_rect.left + layout.line_length;
      window_rect.bottom = window_rect.top + layout.line_width;
      text_rect.SetRect(0, 0, layout.line_length, layout.line_width);
      base_point.SetPoint(0, 0);
    }
    window_layout.window_position_in_screen_coordinate = window_rect;
    window_layout.text_area = text_rect;
    window_layout.base_position = base_point;

    const int next_total_characters = total_characters + layout.text.size();

    // Calculate caret rect assuming its width is 1 pixel.
    // Note that |caret_index| is supposed to be wide character index but
    // |output.preedit().cursor()| is the number of Unicode characters.
    // In case surrogate pair appears, use Util::WideCharsLen to calculate the
    // cursor position as wide character index. See b/4163234 for details.
    // TODO(yukawa): We should use the actual caret size, which can be
    //   obtained by GetGUIThreadInfo API.
    const int caret_index = Util::WideCharsLen(
        Util::SubString(preedit_utf8, 0, output.preedit().cursor()));

    if (total_characters <= caret_index &&
        caret_index < next_total_characters) {
      // In this case, caret points existing character.  We use the left edge
      // of the pointed character.
      const int local_caret_index = caret_index - total_characters;

      const int caret_begin =
          layout.character_positions[local_caret_index].begin;
      // Add 1 because Win32 RECTs are endpoint-exclusive.
      // http://weblogs.asp.net/oldnewthing/archive/2004/02/18/75652.aspx
      // http://www.radiumsoftware.com/0402.html#040222
      const int caret_end = caret_begin + 1;
      if (is_vertical) {
        window_layout.caret_rect =
            CRect(0, caret_begin, layout.line_width, caret_end);
      } else {
        window_layout.caret_rect =
            CRect(caret_begin, 0, caret_end, layout.line_width);
      }
    } else if (((layout_index + 1) == layouts.size()) &&
               (caret_index == next_total_characters)) {
      // In this case, caret points the next to the last character.
      // The composition window should have an extra space to draw the caret if
      // the window can be extended.
      CRect extended_rect(window_layout.window_position_in_screen_coordinate);
      if (is_vertical) {
        if (extended_rect.bottom < area_in_physical_coord.bottom) {
          // Still inside of the |area| if we extend the window.
          extended_rect.InflateRect(0, 0, 0, 1);
        }
        const int caret_begin = extended_rect.Height() - 1;
        // Add 1 because Win32 RECTs are endpoint-exclusive.
        // http://weblogs.asp.net/oldnewthing/archive/2004/02/18/75652.aspx
        // http://www.radiumsoftware.com/0402.html#040222
        const int caret_end = caret_begin + 1;
        window_layout.caret_rect =
            CRect(0, caret_begin, layout.line_width, caret_end);
      } else {
        if (extended_rect.right < area_in_physical_coord.right) {
          // Still inside of the |area| if we extend the window.
          extended_rect.InflateRect(0, 0, 1, 0);
        }
        const int caret_begin = extended_rect.Width() - 1;
        // Add 1 because Win32 RECTs are endpoint-exclusive.
        // http://weblogs.asp.net/oldnewthing/archive/2004/02/18/75652.aspx
        // http://www.radiumsoftware.com/0402.html#040222
        const int caret_end = caret_begin + 1;
        window_layout.caret_rect =
            CRect(caret_begin, 0, caret_end, layout.line_width);
      }
      window_layout.window_position_in_screen_coordinate =
          extended_rect;
    }

    if (total_characters <= cursor_index &&
        cursor_index < next_total_characters &&
        candidate_layout != NULL &&
        !suggest_window_never_hides_preedit) {
      const int local_cursor_index = cursor_index - total_characters;
      CPoint cursor_pos;
      CRect exclusion_area;
      if (is_vertical) {
        cursor_pos.SetPoint(
            0, layout.character_positions[local_cursor_index].begin);
        exclusion_area.SetRect(
            cursor_pos, CPoint(window_rect.Width(), window_rect.Height()));
      } else {
        cursor_pos.SetPoint(
            layout.character_positions[local_cursor_index].begin,
            layout.line_width);
        exclusion_area.SetRect(
            CPoint(layout.character_positions[local_cursor_index].begin, 0),
            CPoint(window_rect.Width(), window_rect.Height()));
      }
      cursor_pos.Offset(window_rect.left, window_rect.top);
      exclusion_area.OffsetRect(window_rect.left, window_rect.top);
      candidate_layout->InitializeWithPositionAndExcludeRegion(
          cursor_pos, exclusion_area);
    }

    const size_t min_segment_index = segment_indices[total_characters];
    const size_t max_segment_index =
        segment_indices[next_total_characters - 1];
    for (size_t segment_index = min_segment_index;
         segment_index <= max_segment_index; ++segment_index) {
      const commands::Preedit::Segment &segment =
          preedit.segment(segment_index);
      if ((segment.annotation() & commands::Preedit::Segment::UNDERLINE) !=
           commands::Preedit::Segment::UNDERLINE &&
          (segment.annotation() & commands::Preedit::Segment::HIGHLIGHT) !=
           commands::Preedit::Segment::HIGHLIGHT) {
        continue;
      }
      const int segment_begin =
          max(segment_lengths[segment_index].begin, total_characters) -
          total_characters;
      const int segment_end =
          min(segment_lengths[segment_index].begin +
              segment_lengths[segment_index].length,
              next_total_characters) - total_characters;
      if (segment_begin >= segment_end) {
        continue;
      }
      DCHECK_GT(segment_end, segment_begin);
      bool show_segment_gap = true;
      if ((segment_index + 1) >= preedit.segment_size()) {
        // If this segment is the last segment, we do not show the gap.
        show_segment_gap = false;
      } else if (segment_lengths[segment_index].begin +
                 segment_lengths[segment_index].length !=
                 segment_end + total_characters) {
        // If this segment continues to the next line, we do not show the
        // gap.  This behavior is different from the composition window
        // drawn by CUAS.
        show_segment_gap = false;
      }

      // As CUAS does, we make a gap in underline between segments.
      // The length of underline will be shortened 20% of the width of
      // the last character.
      const int begin_pos =
          layout.character_positions[segment_begin].begin;
      const int end_pos =
          layout.character_positions[segment_end - 1].begin +
          80 * layout.character_positions[segment_end - 1].length /
          (show_segment_gap ? 100 : 80);

      SegmentMarkerLayout marker;
      if ((segment.annotation() & commands::Preedit::Segment::HIGHLIGHT) ==
           commands::Preedit::Segment::HIGHLIGHT) {
        marker.highlighted = true;
      }

      if (is_vertical) {
        // |CPoint(layout.line_width, begin_pos)| is outside of the
        // window.
        marker.from = CPoint(layout.line_width - 1, begin_pos);
        marker.to = CPoint(layout.line_width - 1, end_pos);
      } else {
        // |CPoint(begin_pos, layout.line_width)| is outside of the
        // window.
        marker.from = CPoint(begin_pos, layout.line_width - 1);
        marker.to = CPoint(end_pos, layout.line_width - 1);
      }
      window_layout.marker_layouts.push_back(marker);
    }
    if (composition_window_layouts != NULL) {
      composition_window_layouts->push_back(window_layout);
    }
    total_line_offset += layout.line_width;
    total_characters += layout.text.size();
  }

  // In this case, suggest window moves to the next line of the preedit text
  // so that suggest window never hides the preedit.
  if (suggest_window_never_hides_preedit &&
      (composition_window_layouts->size() > 0) &&
      (candidate_layout != NULL)) {
    // Initialize the |exclusion_area| with invalid data. These values will
    // be updated to be valid at the first turn of the next for-loop.
    // For example, |exclusion_area.left| will be updated as follows.
    //   exclusion_area.left = min(exclusion_area.left,
    //                             numeric_limits<int>::max());
    CRect exclusion_area(numeric_limits<int>::max(),
                         numeric_limits<int>::max(),
                         numeric_limits<int>::min(),
                         numeric_limits<int>::min());

    for (size_t i = 0; i < composition_window_layouts->size(); ++i) {
      const CompositionWindowLayout &layout = composition_window_layouts->at(i);
      CRect text_area_in_screen_coord = layout.text_area;
      text_area_in_screen_coord.OffsetRect(
          layout.window_position_in_screen_coordinate.left,
          layout.window_position_in_screen_coordinate.top);
      exclusion_area.left = min(exclusion_area.left,
                                text_area_in_screen_coord.left);
      exclusion_area.top = min(exclusion_area.top,
                               text_area_in_screen_coord.top);
      exclusion_area.right = max(exclusion_area.right,
                                 text_area_in_screen_coord.right);
      exclusion_area.bottom = max(exclusion_area.bottom,
                                  text_area_in_screen_coord.bottom);
    }

    CPoint cursor_pos;
    if (is_vertical) {
      cursor_pos.SetPoint(exclusion_area.left, exclusion_area.top);
    } else {
      cursor_pos.SetPoint(exclusion_area.left, exclusion_area.bottom);
    }
    candidate_layout->InitializeWithPositionAndExcludeRegion(
        cursor_pos, exclusion_area);
  }
  return true;
}

bool LayoutManager::ClientPointToScreen(
    HWND src_window_handle,
    const POINT &src_point,
    POINT *dest_point) const {
  if (dest_point == NULL) {
    return false;
  }

  if (!window_position_->IsWindow(src_window_handle)) {
    DLOG(ERROR) << "Invalid window handle.";
    return false;
  }

  CPoint converted = src_point;
  if (window_position_->ClientToScreen(src_window_handle, &converted) ==
      FALSE) {
    DLOG(ERROR) << "ClientToScreen failed.";
    return false;
  }

  *dest_point = converted;
  return true;
}

bool LayoutManager::ClientRectToScreen(
    HWND src_window_handle,
    const RECT &src_rect,
    RECT *dest_rect) const {
  if (dest_rect == NULL) {
    return false;
  }

  if (!window_position_->IsWindow(src_window_handle)) {
    DLOG(ERROR) << "Invalid window handle.";
    return false;
  }

  CPoint top_left(src_rect.left, src_rect.top);
  if (window_position_->ClientToScreen(src_window_handle, &top_left) == FALSE) {
    DLOG(ERROR) << "ClientToScreen failed.";
    return false;
  }

  CPoint bottom_right(src_rect.right, src_rect.bottom);
  if (window_position_->ClientToScreen(src_window_handle, &bottom_right) ==
      FALSE) {
    DLOG(ERROR) << "ClientToScreen failed.";
    return false;
  }

  dest_rect->left = top_left.x;
  dest_rect->top = top_left.y;
  dest_rect->right = bottom_right.x;
  dest_rect->bottom = bottom_right.y;
  return true;
}

bool LayoutManager::LocalPointToScreen(
    HWND src_window_handle,
    const POINT &src_point,
    POINT *dest_point) const {
  if (dest_point == NULL) {
    return false;
  }

  if (!window_position_->IsWindow(src_window_handle)) {
    DLOG(ERROR) << "Invalid window handle.";
    return false;
  }

  CRect window_rect;
  if (window_position_->GetWindowRect(src_window_handle, &window_rect) ==
      FALSE) {
    return false;
  }

  const CPoint offset(window_rect.TopLeft());
  dest_point->x = src_point.x + offset.x;
  dest_point->y = src_point.y + offset.y;

  return true;
}

bool LayoutManager::LocalRectToScreen(
    HWND src_window_handle,
    const RECT &src_rect,
    RECT *dest_rect) const {
  if (dest_rect == NULL) {
    return false;
  }

  if (!window_position_->IsWindow(src_window_handle)) {
    DLOG(ERROR) << "Invalid window handle.";
    return false;
  }

  CRect window_rect;
  if (window_position_->GetWindowRect(src_window_handle, &window_rect) ==
      FALSE) {
    return false;
  }

  const CPoint offset(window_rect.TopLeft());
  dest_rect->left = src_rect.left + offset.x;
  dest_rect->top = src_rect.top + offset.y;
  dest_rect->right = src_rect.right + offset.x;
  dest_rect->bottom = src_rect.bottom + offset.y;

  return true;
}

bool LayoutManager::GetClientRect(
    HWND window_handle, RECT *client_rect) const {
  return window_position_->GetClientRect(window_handle, client_rect);
}

double LayoutManager::GetScalingFactor(HWND window_handle) const {
  const double kDefaultValue = 1.0;
  CRect window_rect_in_logical_coord;
  if (!window_position_->GetWindowRect(window_handle,
                                       &window_rect_in_logical_coord)) {
    return kDefaultValue;
  }

  CPoint top_left_in_physical_coord;
  if (!window_position_->LogicalToPhysicalPoint(
           window_handle, window_rect_in_logical_coord.TopLeft(),
           &top_left_in_physical_coord)) {
    return kDefaultValue;
  }
  CPoint bottom_right_in_physical_coord;
  if (!window_position_->LogicalToPhysicalPoint(
           window_handle, window_rect_in_logical_coord.BottomRight(),
           &bottom_right_in_physical_coord)) {
    return kDefaultValue;
  }
  const CRect window_rect_in_physical_coord(
      top_left_in_physical_coord, bottom_right_in_physical_coord);

  if (window_rect_in_physical_coord == window_rect_in_logical_coord) {
    // No scaling.
    return 1.0;
  }

  // use larger edge to calculate the scaling factor more accurately.
  if (window_rect_in_logical_coord.Width() >
      window_rect_in_logical_coord.Height()) {
    // Use width.
    if (window_rect_in_physical_coord.Width() <= 0 ||
        window_rect_in_logical_coord.Width() <= 0) {
      return kDefaultValue;
    }
    DCHECK_NE(0, window_rect_in_logical_coord.Width()) << "divided-by-zero";
    return (static_cast<double>(window_rect_in_physical_coord.Width()) /
            window_rect_in_logical_coord.Width());
  } else {
    // Use Height.
    if (window_rect_in_physical_coord.Height() <= 0 ||
        window_rect_in_logical_coord.Height() <= 0) {
      return kDefaultValue;
    }
    DCHECK_NE(0, window_rect_in_logical_coord.Height()) << "divided-by-zero";
    return (static_cast<double>(window_rect_in_physical_coord.Height()) /
            window_rect_in_logical_coord.Height());
  }
}

bool LayoutManager::GetDefaultGuiFont(LOGFONTW *logfont) const {
  return system_preference_->GetDefaultGuiFont(logfont);
}

LayoutManager::WritingDirection LayoutManager::GetWritingDirection(
    const commands::RendererCommand_ApplicationInfo &app_info) {
  // |escapement| is the angle between the escapement vector and the x-axis
  // of the device, in tenths of degrees.  In Windows, (Japanese) vertical
  // writing is usually implemented by setting 2700 to the |escapement|,
  // which means the escapement vector is parallel to |Rot(270 deg) * (1, 0)|
  // in the display coordinate.  Note that |escapement| and |orientation| are
  // different concept.  But we only check |escapement| here for application
  // compatibility.
  // Any |escapement| except for 2700 is treated as horizontal, on the
  // strength of IMEINFO::fdwUICaps has only UI_CAP_2700 as for Mozc.
  // See the document of LOGFONT structure and ImmGetProperty API for
  // details.
  // http://msdn.microsoft.com/en-us/library/dd145037.aspx
  // http://msdn.microsoft.com/en-us/library/dd318567.aspx
  // TODO(yukawa): Support arbitrary angle.
  if (!app_info.has_composition_font() ||
      !app_info.composition_font().has_escapement()) {
    return WRITING_DIRECTION_UNSPECIFIED;
  }

  if (app_info.composition_font().escapement() == 2700) {
    return VERTICAL_WRITING;
  }

  return HORIZONTAL_WRITING;
}

bool LayoutManager::LayoutCandidateWindowForSuggestion(
    const commands::RendererCommand::ApplicationInfo &app_info,
    CandidateWindowLayout *candidate_layout) {
  const int compatibility_mode = GetCompatibilityMode(app_info);

  CandidateWindowLayoutParams params;
  if (!ExtractParams(this, compatibility_mode, app_info, &params)) {
    return false;
  }

  if (LayoutCandidateWindowByCompositionTarget(
          params, compatibility_mode, this, candidate_layout)) {
    DCHECK(candidate_layout->initialized());
    return true;
  }

  if ((compatibility_mode & CAN_USE_CANDIDATE_FORM_FOR_SUGGEST) ==
      CAN_USE_CANDIDATE_FORM_FOR_SUGGEST) {
    if (LayoutCandidateWindowByCandidateForm(
            params, compatibility_mode, this, candidate_layout)) {
      DCHECK(candidate_layout->initialized());
      return true;
    }
  }

  if (LayoutCandidateWindowByCaretInfo(
          params, compatibility_mode, this, candidate_layout)) {
    DCHECK(candidate_layout->initialized());
    return true;
  }

  if (LayoutCandidateWindowByCompositionForm(
          params, compatibility_mode, this, candidate_layout)) {
    DCHECK(candidate_layout->initialized());
    return true;
  }

  if (LayoutCandidateWindowByClientRect(
          params, compatibility_mode, this, candidate_layout)) {
    DCHECK(candidate_layout->initialized());
    return true;
  }

  return false;
}

bool LayoutManager::LayoutCandidateWindowForConversion(
    const commands::RendererCommand::ApplicationInfo &app_info,
    CandidateWindowLayout *candidate_layout) {
  const int compatibility_mode = GetCompatibilityMode(app_info);

  CandidateWindowLayoutParams params;
  if (!ExtractParams(this, compatibility_mode, app_info, &params)) {
    return false;
  }

  if (LayoutCandidateWindowByCompositionTarget(
          params, compatibility_mode, this, candidate_layout)) {
    DCHECK(candidate_layout->initialized());
    return true;
  }

  if (LayoutCandidateWindowByCandidateForm(
          params, compatibility_mode, this, candidate_layout)) {
    DCHECK(candidate_layout->initialized());
    return true;
  }

  if (LayoutCandidateWindowByCaretInfo(
          params, compatibility_mode, this, candidate_layout)) {
    DCHECK(candidate_layout->initialized());
    return true;
  }

  if (LayoutCandidateWindowByCompositionForm(
          params, compatibility_mode, this, candidate_layout)) {
    DCHECK(candidate_layout->initialized());
    return true;
  }

  if (LayoutCandidateWindowByClientRect(
          params, compatibility_mode, this, candidate_layout)) {
    DCHECK(candidate_layout->initialized());
    return true;
  }

  return false;
}

int LayoutManager::GetCompatibilityMode(
        const commands::RendererCommand_ApplicationInfo &app_info) {
  if (!app_info.has_target_window_handle()) {
    return COMPATIBILITY_MODE_NONE;
  }
  const HWND target_window = reinterpret_cast<HWND>(
      app_info.target_window_handle());

  if (!window_position_->IsWindow(target_window)) {
    return COMPATIBILITY_MODE_NONE;
  }

  wstring class_name;
  if (!window_position_->GetWindowClassName(target_window, &class_name)) {
    return COMPATIBILITY_MODE_NONE;
  }

  int mode = COMPATIBILITY_MODE_NONE;
  {
    {
      const wchar_t *kUseCandidateFormForSuggest[] = {
          L"Chrome_RenderWidgetHostHWND",
          L"JsTaroCtrl",
          L"OperaWindowClass",
          L"QWidget",
      };
      for (size_t i = 0; i < ARRAYSIZE(kUseCandidateFormForSuggest); ++i) {
        if (kUseCandidateFormForSuggest[i] == class_name) {
          mode |= CAN_USE_CANDIDATE_FORM_FOR_SUGGEST;
          break;
        }
      }
    }
  }

  {
    const wchar_t *kUseLocalCoord[] = {
        L"gdkWindowToplevel",
        L"SunAwtDialog",
        L"SunAwtFrame",
    };
    for (size_t i = 0; i < ARRAYSIZE(kUseLocalCoord); ++i) {
      if (kUseLocalCoord[i] == class_name) {
        mode |= USE_LOCAL_COORD_FOR_CANDIDATE_FORM;
        break;
      }
    }
  }

  {
    const wchar_t *kIgnoreDefaultCompositionForm[] = {
        L"SunAwtDialog",
        L"SunAwtFrame",
    };
    for (size_t i = 0; i < ARRAYSIZE(kIgnoreDefaultCompositionForm); ++i) {
      if (kIgnoreDefaultCompositionForm[i] == class_name) {
        mode |= IGNORE_DEFAULT_COMPOSITION_FORM;
        break;
      }
    }
  }

  {
    const wchar_t *kShowInfolistImmediately[] = {
        L"Emacs",
        L"MEADOW",
    };
    for (size_t i = 0; i < ARRAYSIZE(kShowInfolistImmediately); ++i) {
      if (kShowInfolistImmediately[i] == class_name) {
        mode |= SHOW_INFOLIST_IMMEDIATELY;
        break;
      }
    }
  }

  return mode;
}

bool LayoutManager::LayoutIndicatorWindow(
      const commands::RendererCommand_ApplicationInfo &app_info,
      IndicatorWindowLayout *indicator_layout) {
  if (indicator_layout == nullptr) {
    return false;
  }
  indicator_layout->Clear();

  CandidateWindowLayoutParams params;
  if (!ExtractParams(this,
                     GetCompatibilityMode(app_info),
                     app_info,
                     &params)) {
    return false;
  }

  CRect target_rect;
  if (!GetTargetRectForIndicator(params, *this, &target_rect)) {
    return false;
  }

  indicator_layout->is_vertical = IsVerticalWriting(params);
  indicator_layout->window_rect = target_rect;
  return true;
}

}  // namespace win32
}  // namespace renderer
}  // namespace mozc
