示例#1
0
void CFWL_PictureBoxImp::DrawBkground(CFX_Graphics* pGraphics,
                                      IFWL_ThemeProvider* pTheme,
                                      const CFX_Matrix* pMatrix) {
  IFWL_PictureBoxDP* pPictureDP =
      static_cast<IFWL_PictureBoxDP*>(m_pProperties->m_pDataProvider);
  if (!pPictureDP)
    return;

  CFX_DIBitmap* pPicture = pPictureDP->GetPicture(m_pInterface);
  CFX_Matrix matrix;
  pPictureDP->GetMatrix(m_pInterface, matrix);
  if (!pPicture)
    return;

  matrix.Concat(*pMatrix);
  FX_FLOAT fx = (FX_FLOAT)pPicture->GetWidth();
  FX_FLOAT fy = (FX_FLOAT)pPicture->GetHeight();
  if (fx > m_rtClient.width) {
    fx = m_rtClient.width;
  }
  if (fy > m_rtClient.height) {
    fy = m_rtClient.height;
  }
  pGraphics->DrawImage(pPicture, CFX_PointF((m_rtClient.width - fx) / 2,
                                            (m_rtClient.height - fy) / 2),
                       &matrix);
}
示例#2
0
void CPDF_DeviceBuffer::OutputToDevice() {
  if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) {
    if (m_Matrix.a == 1.0f && m_Matrix.d == 1.0f) {
      m_pDevice->SetDIBits(m_pBitmap.get(), m_Rect.left, m_Rect.top);
    } else {
      m_pDevice->StretchDIBits(m_pBitmap.get(), m_Rect.left, m_Rect.top,
                               m_Rect.Width(), m_Rect.Height());
    }
  } else {
    CFX_DIBitmap buffer;
    m_pDevice->CreateCompatibleBitmap(&buffer, m_pBitmap->GetWidth(),
                                      m_pBitmap->GetHeight());
    m_pContext->GetBackground(&buffer, m_pObject, nullptr, &m_Matrix);
    buffer.CompositeBitmap(0, 0, buffer.GetWidth(), buffer.GetHeight(),
                           m_pBitmap.get(), 0, 0);
    m_pDevice->StretchDIBits(&buffer, m_Rect.left, m_Rect.top, m_Rect.Width(),
                             m_Rect.Height());
  }
}
示例#3
0
FWL_Error CFWL_PictureBoxImp::GetWidgetRect(CFX_RectF& rect,
                                            FX_BOOL bAutoSize) {
  if (bAutoSize) {
    rect.Set(0, 0, 0, 0);
    if (!m_pProperties->m_pDataProvider)
      return FWL_Error::Indefinite;
    CFX_DIBitmap* pBitmap =
        static_cast<IFWL_PictureBoxDP*>(m_pProperties->m_pDataProvider)
            ->GetPicture(m_pInterface);
    if (pBitmap) {
      rect.Set(0, 0, (FX_FLOAT)pBitmap->GetWidth(),
               (FX_FLOAT)pBitmap->GetHeight());
    }
    CFWL_WidgetImp::GetWidgetRect(rect, TRUE);
  } else {
    rect = m_pProperties->m_rtWidget;
  }
  return FWL_Error::Succeeded;
}
示例#4
0
FWL_Error CFWL_WidgetMgr::SetWidgetRect_Native(IFWL_Widget* pWidget,
                                               const CFX_RectF& rect) {
  if (FWL_UseOffscreen(pWidget)) {
    CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget);
    pItem->iRedrawCounter++;
    if (pItem->pOffscreen) {
      CFX_RenderDevice* pDevice = pItem->pOffscreen->GetRenderDevice();
      if (pDevice && pDevice->GetBitmap()) {
        CFX_DIBitmap* pBitmap = pDevice->GetBitmap();
        if (pBitmap->GetWidth() - rect.width > 1 ||
            pBitmap->GetHeight() - rect.height > 1) {
          pItem->pOffscreen.reset();
        }
      }
    }
#if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_)
    pItem->bOutsideChanged = !m_rtScreen.Contains(rect);
#endif
  }
  return FWL_Error::Succeeded;
}
示例#5
0
static CFX_DIBitmap* Transform1bppBitmap(const CFX_DIBSource* pSrc,
                                         const CFX_AffineMatrix* pDestMatrix) {
  ASSERT(pSrc->GetFormat() == FXDIB_1bppRgb ||
         pSrc->GetFormat() == FXDIB_1bppMask ||
         pSrc->GetFormat() == FXDIB_1bppCmyk);
  CFX_DIBExtractor src_bitmap(pSrc);
  CFX_DIBitmap* pSrcBitmap = src_bitmap;
  if (pSrcBitmap == NULL) {
    return NULL;
  }
  int src_width = pSrcBitmap->GetWidth(), src_height = pSrcBitmap->GetHeight();
  uint8_t* src_buf = pSrcBitmap->GetBuffer();
  FX_DWORD src_pitch = pSrcBitmap->GetPitch();
  FX_FLOAT dest_area = pDestMatrix->GetUnitArea();
  FX_FLOAT area_scale =
      FXSYS_Div((FX_FLOAT)(src_width * src_height), dest_area);
  FX_FLOAT size_scale = FXSYS_sqrt(area_scale);
  CFX_AffineMatrix adjusted_matrix(*pDestMatrix);
  adjusted_matrix.Scale(size_scale, size_scale);
  CFX_FloatRect result_rect_f = adjusted_matrix.GetUnitRect();
  FX_RECT result_rect = result_rect_f.GetOutterRect();
  CFX_AffineMatrix src2result;
  src2result.e = adjusted_matrix.c + adjusted_matrix.e;
  src2result.f = adjusted_matrix.d + adjusted_matrix.f;
  src2result.a = adjusted_matrix.a / pSrcBitmap->GetWidth();
  src2result.b = adjusted_matrix.b / pSrcBitmap->GetWidth();
  src2result.c = -adjusted_matrix.c / pSrcBitmap->GetHeight();
  src2result.d = -adjusted_matrix.d / pSrcBitmap->GetHeight();
  src2result.TranslateI(-result_rect.left, -result_rect.top);
  CFX_AffineMatrix result2src;
  result2src.SetReverse(src2result);
  CPDF_FixedMatrix result2src_fix(result2src, 8);
  int result_width = result_rect.Width();
  int result_height = result_rect.Height();
  CFX_DIBitmap* pTempBitmap = new CFX_DIBitmap;
  if (!pTempBitmap->Create(result_width, result_height, pSrc->GetFormat())) {
    delete pTempBitmap;
    if (pSrcBitmap != src_bitmap) {
      delete pSrcBitmap;
    }
    return NULL;
  }
  pTempBitmap->CopyPalette(pSrc->GetPalette());
  uint8_t* dest_buf = pTempBitmap->GetBuffer();
  int dest_pitch = pTempBitmap->GetPitch();
  FXSYS_memset(dest_buf, pSrc->IsAlphaMask() ? 0 : 0xff,
               dest_pitch * result_height);
  if (pSrcBitmap->IsAlphaMask()) {
    for (int dest_y = 0; dest_y < result_height; dest_y++) {
      uint8_t* dest_scan = dest_buf + dest_y * dest_pitch;
      for (int dest_x = 0; dest_x < result_width; dest_x++) {
        int src_x, src_y;
        result2src_fix.Transform(dest_x, dest_y, src_x, src_y);
        if (src_x < 0 || src_x >= src_width || src_y < 0 ||
            src_y >= src_height) {
          continue;
        }
        if (!((src_buf + src_pitch * src_y)[src_x / 8] &
              (1 << (7 - src_x % 8)))) {
          continue;
        }
        dest_scan[dest_x / 8] |= 1 << (7 - dest_x % 8);
      }
    }
  } else {
    for (int dest_y = 0; dest_y < result_height; dest_y++) {
      uint8_t* dest_scan = dest_buf + dest_y * dest_pitch;
      for (int dest_x = 0; dest_x < result_width; dest_x++) {
        int src_x, src_y;
        result2src_fix.Transform(dest_x, dest_y, src_x, src_y);
        if (src_x < 0 || src_x >= src_width || src_y < 0 ||
            src_y >= src_height) {
          continue;
        }
        if ((src_buf + src_pitch * src_y)[src_x / 8] & (1 << (7 - src_x % 8))) {
          continue;
        }
        dest_scan[dest_x / 8] &= ~(1 << (7 - dest_x % 8));
      }
    }
  }
  if (pSrcBitmap != src_bitmap) {
    delete pSrcBitmap;
  }
  return pTempBitmap;
}
示例#6
0
void CPDF_RenderStatus::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap,
        int left,
        int top,
        FX_ARGB mask_argb,
        int bitmap_alpha,
        int blend_mode,
        int Transparency) {
    if (pDIBitmap == NULL) {
        return;
    }
    FX_BOOL bIsolated = Transparency & PDFTRANS_ISOLATED;
    FX_BOOL bGroup = Transparency & PDFTRANS_GROUP;
    if (blend_mode == FXDIB_BLEND_NORMAL) {
        if (!pDIBitmap->IsAlphaMask()) {
            if (bitmap_alpha < 255) {
                pDIBitmap->MultiplyAlpha(bitmap_alpha);
            }
            if (m_pDevice->SetDIBits(pDIBitmap, left, top)) {
                return;
            }
        } else {
            FX_DWORD fill_argb = m_Options.TranslateColor(mask_argb);
            if (bitmap_alpha < 255) {
                ((uint8_t*)&fill_argb)[3] =
                    ((uint8_t*)&fill_argb)[3] * bitmap_alpha / 255;
            }
            if (m_pDevice->SetBitMask(pDIBitmap, left, top, fill_argb)) {
                return;
            }
        }
    }
    FX_BOOL bBackAlphaRequired = blend_mode && bIsolated && !m_bDropObjects;
    FX_BOOL bGetBackGround =
        ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) ||
        (!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) &&
         (m_pDevice->GetRenderCaps() & FXRC_GET_BITS) && !bBackAlphaRequired);
    if (bGetBackGround) {
        if (bIsolated || !bGroup) {
            if (pDIBitmap->IsAlphaMask()) {
                return;
            }
            m_pDevice->SetDIBits(pDIBitmap, left, top, blend_mode);
        } else {
            FX_RECT rect(left, top, left + pDIBitmap->GetWidth(),
                         top + pDIBitmap->GetHeight());
            rect.Intersect(m_pDevice->GetClipBox());
            CFX_DIBitmap* pClone = NULL;
            FX_BOOL bClone = FALSE;
            if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) {
                bClone = TRUE;
                pClone = m_pDevice->GetBackDrop()->Clone(&rect);
                CFX_DIBitmap* pForeBitmap = m_pDevice->GetBitmap();
                pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(),
                                        pForeBitmap, rect.left, rect.top);
                left = left >= 0 ? 0 : left;
                top = top >= 0 ? 0 : top;
                if (!pDIBitmap->IsAlphaMask())
                    pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(),
                                            pDIBitmap, left, top, blend_mode);
                else
                    pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(),
                                          pDIBitmap, mask_argb, left, top, blend_mode);
            } else {
                pClone = pDIBitmap;
            }
            if (m_pDevice->GetBackDrop()) {
                m_pDevice->SetDIBits(pClone, rect.left, rect.top);
            } else {
                if (pDIBitmap->IsAlphaMask()) {
                    return;
                }
                m_pDevice->SetDIBits(pDIBitmap, rect.left, rect.top, blend_mode);
            }
            if (bClone) {
                delete pClone;
            }
        }
        return;
    }
    int back_left, back_top;
    FX_RECT rect(left, top, left + pDIBitmap->GetWidth(),
                 top + pDIBitmap->GetHeight());
    nonstd::unique_ptr<CFX_DIBitmap> pBackdrop(
        GetBackdrop(m_pCurObj, rect, back_left, back_top,
                    blend_mode > FXDIB_BLEND_NORMAL && bIsolated));
    if (!pBackdrop)
        return;

    if (!pDIBitmap->IsAlphaMask()) {
        pBackdrop->CompositeBitmap(left - back_left, top - back_top,
                                   pDIBitmap->GetWidth(), pDIBitmap->GetHeight(),
                                   pDIBitmap, 0, 0, blend_mode);
    } else {
        pBackdrop->CompositeMask(left - back_left, top - back_top,
                                 pDIBitmap->GetWidth(), pDIBitmap->GetHeight(),
                                 pDIBitmap, mask_argb, 0, 0, blend_mode);
    }

    nonstd::unique_ptr<CFX_DIBitmap> pBackdrop1(new CFX_DIBitmap);
    pBackdrop1->Create(pBackdrop->GetWidth(), pBackdrop->GetHeight(),
                       FXDIB_Rgb32);
    pBackdrop1->Clear((FX_DWORD)-1);
    pBackdrop1->CompositeBitmap(0, 0, pBackdrop->GetWidth(),
                                pBackdrop->GetHeight(), pBackdrop.get(), 0, 0);
    pBackdrop = nonstd::move(pBackdrop1);
    m_pDevice->SetDIBits(pBackdrop.get(), back_left, back_top);
}
示例#7
0
FWL_ERR CFWL_PushButtonImp::DrawWidget(CFX_Graphics* pGraphics,
                                       const CFX_Matrix* pMatrix) {
  if (!pGraphics)
    return FWL_ERR_Indefinite;
  if (!m_pProperties->m_pThemeProvider)
    return FWL_ERR_Indefinite;
  IFWL_PushButtonDP* pData =
      static_cast<IFWL_PushButtonDP*>(m_pProperties->m_pDataProvider);
  CFX_DIBitmap* pPicture = NULL;
  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
  if (HasBorder()) {
    DrawBorder(pGraphics, FWL_PART_PSB_Border, m_pProperties->m_pThemeProvider,
               pMatrix);
  }
  if (HasEdge()) {
    DrawEdge(pGraphics, FWL_PART_PSB_Edge, m_pProperties->m_pThemeProvider,
             pMatrix);
  }
  DrawBkground(pGraphics, m_pProperties->m_pThemeProvider, pMatrix);
  CFX_Matrix matrix;
  matrix.Concat(*pMatrix);
  FX_FLOAT iPicwidth = 0;
  FX_FLOAT ipicheight = 0;
  CFX_WideString wsCaption;
  if (pData) {
    pData->GetCaption(m_pInterface, wsCaption);
  }
  CFX_RectF rtText;
  rtText.Set(0, 0, 0, 0);
  if (!wsCaption.IsEmpty()) {
    CalcTextRect(wsCaption, pTheme, 0, m_iTTOAlign, rtText);
  }
  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_PSB_ModeMask) {
    case FWL_STYLEEXT_PSB_TextOnly:
      DrawText(pGraphics, m_pProperties->m_pThemeProvider, &matrix);
      break;
    case FWL_STYLEEXT_PSB_IconOnly:
      if (pData) {
        pPicture = pData->GetPicture(m_pInterface);
      }
      if (pPicture) {
        CFX_PointF point;
        switch (m_iTTOAlign) {
          case 0: {
            point.x = m_rtClient.left;
            point.y = m_rtClient.top;
            break;
          }
          case 1: {
            point.x = m_rtClient.left +
                      (m_rtClient.width / 2 - pPicture->GetWidth() / 2);
            point.y = m_rtClient.top;
            break;
          }
          case 2:
            point.x = m_rtClient.left + m_rtClient.width - pPicture->GetWidth();
            point.y = m_rtClient.top;
            break;
          case 4:
            point.x = m_rtClient.left;
            point.y = m_rtClient.top + m_rtClient.height / 2 -
                      pPicture->GetHeight() / 2;
            break;
          case 5:
            point.x = m_rtClient.left +
                      (m_rtClient.width / 2 - pPicture->GetWidth() / 2);
            point.y = m_rtClient.top + m_rtClient.height / 2 -
                      pPicture->GetHeight() / 2;
            break;
          case 6:
            point.x = m_rtClient.left + m_rtClient.width - pPicture->GetWidth();
            point.y = m_rtClient.top + m_rtClient.height / 2 -
                      pPicture->GetHeight() / 2;
            break;
          case 8:
            point.x = m_rtClient.left;
            point.y =
                m_rtClient.top + m_rtClient.height - pPicture->GetHeight();
            break;
          case 9:
            point.x = m_rtClient.left +
                      (m_rtClient.width / 2 - pPicture->GetWidth() / 2);
            point.y =
                m_rtClient.top + m_rtClient.height - pPicture->GetHeight();
            break;
          case 10:
            point.x = m_rtClient.left + m_rtClient.width - pPicture->GetWidth();
            point.y =
                m_rtClient.top + m_rtClient.height - pPicture->GetHeight();
            break;
        }
        pGraphics->DrawImage(pPicture, point, &matrix);
      }
      break;
    case FWL_STYLEEXT_PSB_TextIcon:
      if (pPicture) {
        CFX_PointF point;
        switch (m_iTTOAlign) {
          case 0: {
            point.x = m_rtClient.left;
            point.y = m_rtClient.top;
            iPicwidth = (FX_FLOAT)(pPicture->GetWidth() - 7);
            ipicheight =
                pPicture->GetHeight() / 2 - m_rtCaption.top - rtText.height / 2;
            break;
          }
          case 1: {
            point.x =
                m_rtClient.left + (m_rtClient.width / 2 -
                                   (pPicture->GetWidth() + rtText.width) / 2);
            point.y = m_rtClient.top;
            iPicwidth = pPicture->GetWidth() -
                        ((m_rtClient.width) / 2 - rtText.width / 2 - point.x) +
                        rtText.width / 2 - 7;
            ipicheight =
                pPicture->GetHeight() / 2 - m_rtCaption.top - rtText.height / 2;
            break;
          }
          case 2:
            point.x = m_rtClient.left + m_rtClient.width -
                      pPicture->GetWidth() - rtText.width;
            point.y = m_rtClient.top;
            iPicwidth = m_rtClient.left + m_rtClient.width - point.x -
                        pPicture->GetWidth() - rtText.width + 7;
            ipicheight =
                pPicture->GetHeight() / 2 - m_rtCaption.top - rtText.height / 2;
            break;
          case 4:
            point.x = m_rtClient.left;
            point.y = m_rtClient.top + m_rtClient.height / 2 -
                      pPicture->GetHeight() / 2;
            iPicwidth = m_rtClient.left + pPicture->GetWidth() - 7;
            break;
          case 5:
            point.x =
                m_rtClient.left + (m_rtClient.width / 2 -
                                   (pPicture->GetWidth() + rtText.width) / 2);
            point.y = m_rtClient.top + m_rtClient.height / 2 -
                      pPicture->GetHeight() / 2;
            iPicwidth = pPicture->GetWidth() -
                        ((m_rtClient.width) / 2 - rtText.width / 2 - point.x) +
                        rtText.width / 2 - 7;
            break;
          case 6:
            point.x = m_rtClient.left + m_rtClient.width -
                      pPicture->GetWidth() - rtText.width;
            point.y = m_rtClient.top + m_rtClient.height / 2 -
                      pPicture->GetHeight() / 2;
            iPicwidth = m_rtClient.left + m_rtClient.width - point.x -
                        pPicture->GetWidth() - rtText.width + 7;
            break;
          case 8:
            point.x = m_rtClient.left;
            point.y =
                m_rtClient.top + m_rtClient.height - pPicture->GetHeight();
            iPicwidth = (FX_FLOAT)(pPicture->GetWidth() - 7);
            ipicheight -= rtText.height / 2;
            break;
          case 9:
            point.x =
                m_rtClient.left + (m_rtClient.width / 2 -
                                   (pPicture->GetWidth() + rtText.width) / 2);
            point.y =
                m_rtClient.top + m_rtClient.height - pPicture->GetHeight();
            iPicwidth = pPicture->GetWidth() -
                        ((m_rtClient.width) / 2 - rtText.width / 2 - point.x) +
                        rtText.width / 2 - 7;
            ipicheight -= rtText.height / 2;
            break;
          case 10:
            point.x = m_rtClient.left + m_rtClient.width -
                      pPicture->GetWidth() - rtText.width;
            point.y =
                m_rtClient.top + m_rtClient.height - pPicture->GetHeight();
            iPicwidth = m_rtClient.left + m_rtClient.width - point.x -
                        pPicture->GetWidth() - rtText.width + 7;
            ipicheight -= rtText.height / 2;
            break;
        }
        pGraphics->DrawImage(pPicture, point, &matrix);
      }
      matrix.e += m_rtClient.left + iPicwidth;
      matrix.f += m_rtClient.top + ipicheight;
      DrawText(pGraphics, m_pProperties->m_pThemeProvider, &matrix);
      break;
  }
  return FWL_ERR_Succeeded;
}
示例#8
0
DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc, FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y,
                                       int rotate, int flags)
{
    if (page==NULL) return;
    CPDF_Page* pPage = (CPDF_Page*)page;

    CRenderContext* pContext = FX_NEW CRenderContext;
    pPage->SetPrivateData((void*)1, pContext, DropContext);

#ifndef _WIN32_WCE
    CFX_DIBitmap* pBitmap = NULL;
    FX_BOOL bBackgroundAlphaNeeded=FALSE;
    bBackgroundAlphaNeeded = pPage->BackgroundAlphaNeeded();
    if (bBackgroundAlphaNeeded)
    {

        pBitmap = FX_NEW CFX_DIBitmap;
        pBitmap->Create(size_x, size_y, FXDIB_Argb);
        pBitmap->Clear(0x00ffffff);
#ifdef _SKIA_SUPPORT_
        pContext->m_pDevice = FX_NEW CFX_SkiaDevice;
        ((CFX_SkiaDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap);
#else
        pContext->m_pDevice = FX_NEW CFX_FxgeDevice;
        ((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap);
#endif
    }
    else
        pContext->m_pDevice = FX_NEW CFX_WindowsDevice(dc);
    if (flags & FPDF_NO_CATCH)
        Func_RenderPage(pContext, page, start_x, start_y, size_x, size_y, rotate, flags,TRUE,NULL);
    else {
        try {
            Func_RenderPage(pContext, page, start_x, start_y, size_x, size_y, rotate, flags,TRUE,NULL);
        } catch (...) {
        }
    }
    if (bBackgroundAlphaNeeded)
    {
        if (pBitmap)
        {
            CFX_WindowsDevice WinDC(dc);

            if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER)
            {
                CFX_DIBitmap* pDst = FX_NEW CFX_DIBitmap;
                pDst->Create(pBitmap->GetWidth(), pBitmap->GetHeight(),FXDIB_Rgb32);
                FXSYS_memcpy(pDst->GetBuffer(), pBitmap->GetBuffer(), pBitmap->GetPitch()*pBitmap->GetHeight());
//				WinDC.SetDIBits(pDst,0,0);
                WinDC.StretchDIBits(pDst,0,0,size_x*2,size_y*2);
                delete pDst;
            }
            else
                WinDC.SetDIBits(pBitmap,0,0);

        }
    }
#else
    // get clip region
    RECT rect, cliprect;
    rect.left = start_x;
    rect.top = start_y;
    rect.right = start_x + size_x;
    rect.bottom = start_y + size_y;
    GetClipBox(dc, &cliprect);
    IntersectRect(&rect, &rect, &cliprect);
    int width = rect.right - rect.left;
    int height = rect.bottom - rect.top;

#ifdef DEBUG_TRACE
    {
        char str[128];
        sprintf(str, "Rendering DIB %d x %d", width, height);
        CPDF_ModuleMgr::Get()->ReportError(999, str);
    }
#endif

    // Create a DIB section
    LPVOID pBuffer;
    BITMAPINFOHEADER bmih;
    FXSYS_memset(&bmih, 0, sizeof bmih);
    bmih.biSize = sizeof bmih;
    bmih.biBitCount = 24;
    bmih.biHeight = -height;
    bmih.biPlanes = 1;
    bmih.biWidth = width;
    pContext->m_hBitmap = CreateDIBSection(dc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, &pBuffer, NULL, 0);
    if (pContext->m_hBitmap == NULL) {
#if defined(DEBUG) || defined(_DEBUG)
        char str[128];
        sprintf(str, "Error CreateDIBSection: %d x %d, error code = %d", width, height, GetLastError());
        CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, str);
#else
        CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, NULL);
#endif
    }
    FXSYS_memset(pBuffer, 0xff, height*((width*3+3)/4*4));

#ifdef DEBUG_TRACE
    {
        CPDF_ModuleMgr::Get()->ReportError(999, "DIBSection created");
    }
#endif

    // Create a device with this external buffer
    pContext->m_pBitmap = FX_NEW CFX_DIBitmap;
    pContext->m_pBitmap->Create(width, height, FXDIB_Rgb, (FX_LPBYTE)pBuffer);
    pContext->m_pDevice = FX_NEW CPDF_FxgeDevice;
    ((CPDF_FxgeDevice*)pContext->m_pDevice)->Attach(pContext->m_pBitmap);

#ifdef DEBUG_TRACE
    CPDF_ModuleMgr::Get()->ReportError(999, "Ready for PDF rendering");
#endif

    // output to bitmap device
    if (flags & FPDF_NO_CATCH)
        Func_RenderPage(pContext, page, start_x - rect.left, start_y - rect.top, size_x, size_y, rotate, flags);
    else {
        try {
            Func_RenderPage(pContext, page, start_x - rect.left, start_y - rect.top, size_x, size_y, rotate, flags);
        } catch (...) {
        }
    }

#ifdef DEBUG_TRACE
    CPDF_ModuleMgr::Get()->ReportError(999, "Finished PDF rendering");
#endif

    // Now output to real device
    HDC hMemDC = CreateCompatibleDC(dc);
    if (hMemDC == NULL) {
#if defined(DEBUG) || defined(_DEBUG)
        char str[128];
        sprintf(str, "Error CreateCompatibleDC. Error code = %d", GetLastError());
        CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, str);
#else
        CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, NULL);
#endif
    }

    HGDIOBJ hOldBitmap = SelectObject(hMemDC, pContext->m_hBitmap);

#ifdef DEBUG_TRACE
    CPDF_ModuleMgr::Get()->ReportError(999, "Ready for screen rendering");
#endif

    BitBlt(dc, rect.left, rect.top, width, height, hMemDC, 0, 0, SRCCOPY);
    SelectObject(hMemDC, hOldBitmap);
    DeleteDC(hMemDC);

#ifdef DEBUG_TRACE
    CPDF_ModuleMgr::Get()->ReportError(999, "Finished screen rendering");
#endif

#endif
    if (bBackgroundAlphaNeeded)
    {
        if (pBitmap)
            delete pBitmap;
        pBitmap = NULL;
    }
    delete pContext;
    pPage->RemovePrivateData((void*)1);
}