Home | History | Annotate | Download | only in render
      1 // Copyright 2016 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "core/fpdfapi/render/cpdf_scaledrenderbuffer.h"
      8 
      9 #include "core/fpdfapi/render/cpdf_rendercontext.h"
     10 #include "core/fpdfapi/render/cpdf_renderoptions.h"
     11 #include "core/fxge/cfx_fxgedevice.h"
     12 #include "core/fxge/cfx_renderdevice.h"
     13 #include "third_party/base/ptr_util.h"
     14 
     15 #define _FPDFAPI_IMAGESIZE_LIMIT_ (30 * 1024 * 1024)
     16 
     17 CPDF_ScaledRenderBuffer::CPDF_ScaledRenderBuffer() {}
     18 
     19 CPDF_ScaledRenderBuffer::~CPDF_ScaledRenderBuffer() {}
     20 
     21 bool CPDF_ScaledRenderBuffer::Initialize(CPDF_RenderContext* pContext,
     22                                          CFX_RenderDevice* pDevice,
     23                                          const FX_RECT& pRect,
     24                                          const CPDF_PageObject* pObj,
     25                                          const CPDF_RenderOptions* pOptions,
     26                                          int max_dpi) {
     27   m_pDevice = pDevice;
     28   if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS)
     29     return true;
     30 
     31   m_pContext = pContext;
     32   m_Rect = pRect;
     33   m_pObject = pObj;
     34   m_Matrix.Translate(-pRect.left, -pRect.top);
     35   int horz_size = pDevice->GetDeviceCaps(FXDC_HORZ_SIZE);
     36   int vert_size = pDevice->GetDeviceCaps(FXDC_VERT_SIZE);
     37   if (horz_size && vert_size && max_dpi) {
     38     int dpih =
     39         pDevice->GetDeviceCaps(FXDC_PIXEL_WIDTH) * 254 / (horz_size * 10);
     40     int dpiv =
     41         pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10);
     42     if (dpih > max_dpi)
     43       m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f);
     44     if (dpiv > max_dpi)
     45       m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv);
     46   }
     47   m_pBitmapDevice = pdfium::MakeUnique<CFX_FxgeDevice>();
     48   FXDIB_Format dibFormat = FXDIB_Rgb;
     49   int32_t bpp = 24;
     50   if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_ALPHA_OUTPUT) {
     51     dibFormat = FXDIB_Argb;
     52     bpp = 32;
     53   }
     54   while (1) {
     55     CFX_FloatRect rect(pRect);
     56     m_Matrix.TransformRect(rect);
     57     FX_RECT bitmap_rect = rect.GetOuterRect();
     58     int32_t iWidth = bitmap_rect.Width();
     59     int32_t iHeight = bitmap_rect.Height();
     60     int32_t iPitch = (iWidth * bpp + 31) / 32 * 4;
     61     if (iWidth * iHeight < 1)
     62       return false;
     63 
     64     if (iPitch * iHeight <= _FPDFAPI_IMAGESIZE_LIMIT_ &&
     65         m_pBitmapDevice->Create(iWidth, iHeight, dibFormat, nullptr)) {
     66       break;
     67     }
     68     m_Matrix.Scale(0.5f, 0.5f);
     69   }
     70   m_pContext->GetBackground(m_pBitmapDevice->GetBitmap(), m_pObject, pOptions,
     71                             &m_Matrix);
     72   return true;
     73 }
     74 
     75 void CPDF_ScaledRenderBuffer::OutputToDevice() {
     76   if (m_pBitmapDevice) {
     77     m_pDevice->StretchDIBits(m_pBitmapDevice->GetBitmap(), m_Rect.left,
     78                              m_Rect.top, m_Rect.Width(), m_Rect.Height());
     79   }
     80 }
     81