예제 #1
0
FX_BOOL CPDF_RenderStatus::ProcessTransparency(CPDF_PageObject* pPageObj,
                                               const CFX_Matrix* pObj2Device) {
#if defined _SKIA_SUPPORT_
  DebugVerifyDeviceIsPreMultiplied();
#endif
  int blend_type = pPageObj->m_GeneralState.GetBlendType();
  if (blend_type == FXDIB_BLEND_UNSUPPORTED)
    return TRUE;

  CPDF_Dictionary* pSMaskDict =
      ToDictionary(pPageObj->m_GeneralState.GetSoftMask());
  if (pSMaskDict) {
    if (pPageObj->IsImage() &&
        pPageObj->AsImage()->GetImage()->GetDict()->KeyExist("SMask")) {
      pSMaskDict = nullptr;
    }
  }
  CPDF_Dictionary* pFormResource = nullptr;
  FX_FLOAT group_alpha = 1.0f;
  int Transparency = m_Transparency;
  FX_BOOL bGroupTransparent = FALSE;
  if (pPageObj->IsForm()) {
    const CPDF_FormObject* pFormObj = pPageObj->AsForm();
    group_alpha = pFormObj->m_GeneralState.GetFillAlpha();
    Transparency = pFormObj->m_pForm->m_Transparency;
    bGroupTransparent = !!(Transparency & PDFTRANS_ISOLATED);
    if (pFormObj->m_pForm->m_pFormDict) {
      pFormResource = pFormObj->m_pForm->m_pFormDict->GetDictBy("Resources");
    }
  }
  bool bTextClip =
      (pPageObj->m_ClipPath && pPageObj->m_ClipPath.GetTextCount() &&
       m_pDevice->GetDeviceClass() == FXDC_DISPLAY &&
       !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP));
  if ((m_Options.m_Flags & RENDER_OVERPRINT) && pPageObj->IsImage() &&
      pPageObj->m_GeneralState.GetFillOP() &&
      pPageObj->m_GeneralState.GetStrokeOP()) {
    CPDF_Document* pDocument = nullptr;
    CPDF_Page* pPage = nullptr;
    if (m_pContext->GetPageCache()) {
      pPage = m_pContext->GetPageCache()->GetPage();
      pDocument = pPage->m_pDocument;
    } else {
      pDocument = pPageObj->AsImage()->GetImage()->GetDocument();
    }
    CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : nullptr;
    CPDF_Object* pCSObj = pPageObj->AsImage()
                              ->GetImage()
                              ->GetStream()
                              ->GetDict()
                              ->GetDirectObjectBy("ColorSpace");
    CPDF_ColorSpace* pColorSpace =
        pDocument->LoadColorSpace(pCSObj, pPageResources);
    if (pColorSpace) {
      int format = pColorSpace->GetFamily();
      if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION ||
          format == PDFCS_DEVICEN) {
        blend_type = FXDIB_BLEND_DARKEN;
      }
      pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
    }
  }
  if (!pSMaskDict && group_alpha == 1.0f && blend_type == FXDIB_BLEND_NORMAL &&
      !bTextClip && !bGroupTransparent) {
    return FALSE;
  }
  bool isolated = !!(Transparency & PDFTRANS_ISOLATED);
  if (m_bPrint) {
    FX_BOOL bRet = FALSE;
    int rendCaps = m_pDevice->GetRenderCaps();
    if (!((Transparency & PDFTRANS_ISOLATED) || pSMaskDict || bTextClip) &&
        (rendCaps & FXRC_BLEND_MODE)) {
      int oldBlend = m_curBlend;
      m_curBlend = blend_type;
      bRet = DrawObjWithBlend(pPageObj, pObj2Device);
      m_curBlend = oldBlend;
    }
    if (!bRet) {
      DrawObjWithBackground(pPageObj, pObj2Device);
    }
    return TRUE;
  }
  FX_RECT rect = pPageObj->GetBBox(pObj2Device);
  rect.Intersect(m_pDevice->GetClipBox());
  if (rect.IsEmpty()) {
    return TRUE;
  }
  CFX_Matrix deviceCTM = m_pDevice->GetCTM();
  FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a);
  FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d);
  int width = FXSYS_round((FX_FLOAT)rect.Width() * scaleX);
  int height = FXSYS_round((FX_FLOAT)rect.Height() * scaleY);
  CFX_FxgeDevice bitmap_device;
  std::unique_ptr<CFX_DIBitmap> oriDevice;
  if (!isolated && (m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
    oriDevice.reset(new CFX_DIBitmap);
    if (!m_pDevice->CreateCompatibleBitmap(oriDevice.get(), width, height))
      return TRUE;
    m_pDevice->GetDIBits(oriDevice.get(), rect.left, rect.top);
  }
  if (!bitmap_device.Create(width, height, FXDIB_Argb, oriDevice.get()))
    return TRUE;
  CFX_DIBitmap* bitmap = bitmap_device.GetBitmap();
  bitmap->Clear(0);
  CFX_Matrix new_matrix = *pObj2Device;
  new_matrix.TranslateI(-rect.left, -rect.top);
  new_matrix.Scale(scaleX, scaleY);
  std::unique_ptr<CFX_DIBitmap> pTextMask;
  if (bTextClip) {
    pTextMask.reset(new CFX_DIBitmap);
    if (!pTextMask->Create(width, height, FXDIB_8bppMask))
      return TRUE;

    pTextMask->Clear(0);
    CFX_FxgeDevice text_device;
    text_device.Attach(pTextMask.get(), false, nullptr, false);
    for (uint32_t i = 0; i < pPageObj->m_ClipPath.GetTextCount(); i++) {
      CPDF_TextObject* textobj = pPageObj->m_ClipPath.GetText(i);
      if (!textobj) {
        break;
      }
      CFX_Matrix text_matrix;
      textobj->GetTextMatrix(&text_matrix);
      CPDF_TextRenderer::DrawTextPath(
          &text_device, textobj->m_nChars, textobj->m_pCharCodes,
          textobj->m_pCharPos, textobj->m_TextState.GetFont(),
          textobj->m_TextState.GetFontSize(), &text_matrix, &new_matrix,
          textobj->m_GraphState.GetObject(), (FX_ARGB)-1, 0, nullptr, 0);
    }
  }
  CPDF_RenderStatus bitmap_render;
  bitmap_render.Initialize(m_pContext, &bitmap_device, nullptr, m_pStopObj,
                           nullptr, nullptr, &m_Options, 0, m_bDropObjects,
                           pFormResource, TRUE);
  bitmap_render.ProcessObjectNoClip(pPageObj, &new_matrix);
  m_bStopped = bitmap_render.m_bStopped;
  if (pSMaskDict) {
    CFX_Matrix smask_matrix = *pPageObj->m_GeneralState.GetSMaskMatrix();
    smask_matrix.Concat(*pObj2Device);
    std::unique_ptr<CFX_DIBSource> pSMaskSource(
        LoadSMask(pSMaskDict, &rect, &smask_matrix));
    if (pSMaskSource)
      bitmap->MultiplyAlpha(pSMaskSource.get());
  }
  if (pTextMask) {
    bitmap->MultiplyAlpha(pTextMask.get());
    pTextMask.reset();
  }
  int32_t blitAlpha = 255;
  if (Transparency & PDFTRANS_GROUP && group_alpha != 1.0f) {
    blitAlpha = (int32_t)(group_alpha * 255);
#ifndef _SKIA_SUPPORT_
    bitmap->MultiplyAlpha(blitAlpha);
    blitAlpha = 255;
#endif
  }
  Transparency = m_Transparency;
  if (pPageObj->IsForm()) {
    Transparency |= PDFTRANS_GROUP;
  }
  CompositeDIBitmap(bitmap, rect.left, rect.top, 0, blitAlpha, blend_type,
                    Transparency);
#if defined _SKIA_SUPPORT_
  DebugVerifyDeviceIsPreMultiplied();
#endif
  return TRUE;
}
예제 #2
0
FX_BOOL CPDF_RenderStatus::ProcessTransparency(
    const CPDF_PageObject* pPageObj,
    const CFX_AffineMatrix* pObj2Device) {
  const CPDF_GeneralStateData* pGeneralState = pPageObj->m_GeneralState;
  int blend_type =
      pGeneralState ? pGeneralState->m_BlendType : FXDIB_BLEND_NORMAL;
  if (blend_type == FXDIB_BLEND_UNSUPPORTED) {
    return TRUE;
  }
  CPDF_Dictionary* pSMaskDict =
      pGeneralState ? ToDictionary(pGeneralState->m_pSoftMask) : NULL;
  if (pSMaskDict) {
    if (pPageObj->m_Type == PDFPAGE_IMAGE &&
        ((CPDF_ImageObject*)pPageObj)
            ->m_pImage->GetDict()
            ->KeyExist(FX_BSTRC("SMask"))) {
      pSMaskDict = NULL;
    }
  }
  CPDF_Dictionary* pFormResource = NULL;
  FX_FLOAT group_alpha = 1.0f;
  int Transparency = m_Transparency;
  FX_BOOL bGroupTransparent = FALSE;
  if (pPageObj->m_Type == PDFPAGE_FORM) {
    CPDF_FormObject* pFormObj = (CPDF_FormObject*)pPageObj;
    const CPDF_GeneralStateData* pStateData =
        pFormObj->m_GeneralState.GetObject();
    if (pStateData) {
      group_alpha = pStateData->m_FillAlpha;
    }
    Transparency = pFormObj->m_pForm->m_Transparency;
    bGroupTransparent = !!(Transparency & PDFTRANS_ISOLATED);
    if (pFormObj->m_pForm->m_pFormDict) {
      pFormResource = pFormObj->m_pForm->m_pFormDict->GetDict("Resources");
    }
  }
  FX_BOOL bTextClip = FALSE;
  if (pPageObj->m_ClipPath.NotNull() && pPageObj->m_ClipPath.GetTextCount() &&
      m_pDevice->GetDeviceClass() == FXDC_DISPLAY &&
      !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)) {
    bTextClip = TRUE;
  }
  if ((m_Options.m_Flags & RENDER_OVERPRINT) &&
      pPageObj->m_Type == PDFPAGE_IMAGE && pGeneralState &&
      pGeneralState->m_FillOP && pGeneralState->m_StrokeOP) {
    CPDF_Document* pDocument = NULL;
    CPDF_Page* pPage = NULL;
    if (m_pContext->m_pPageCache) {
      pPage = m_pContext->m_pPageCache->GetPage();
      pDocument = pPage->m_pDocument;
    } else {
      pDocument = ((CPDF_ImageObject*)pPageObj)->m_pImage->GetDocument();
    }
    CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : NULL;
    CPDF_Object* pCSObj = ((CPDF_ImageObject*)pPageObj)
                              ->m_pImage->GetStream()
                              ->GetDict()
                              ->GetElementValue(FX_BSTRC("ColorSpace"));
    CPDF_ColorSpace* pColorSpace =
        pDocument->LoadColorSpace(pCSObj, pPageResources);
    if (pColorSpace) {
      int format = pColorSpace->GetFamily();
      if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION ||
          format == PDFCS_DEVICEN) {
        blend_type = FXDIB_BLEND_DARKEN;
      }
      pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
    }
  }
  if (pSMaskDict == NULL && group_alpha == 1.0f &&
      blend_type == FXDIB_BLEND_NORMAL && !bTextClip && !bGroupTransparent) {
    return FALSE;
  }
  FX_BOOL isolated = Transparency & PDFTRANS_ISOLATED;
  if (m_bPrint) {
    FX_BOOL bRet = FALSE;
    int rendCaps = m_pDevice->GetRenderCaps();
    if (!((Transparency & PDFTRANS_ISOLATED) || pSMaskDict || bTextClip) &&
        (rendCaps & FXRC_BLEND_MODE)) {
      int oldBlend = m_curBlend;
      m_curBlend = blend_type;
      bRet = DrawObjWithBlend(pPageObj, pObj2Device);
      m_curBlend = oldBlend;
    }
    if (!bRet) {
      DrawObjWithBackground(pPageObj, pObj2Device);
    }
    return TRUE;
  }
  FX_RECT rect = pPageObj->GetBBox(pObj2Device);
  rect.Intersect(m_pDevice->GetClipBox());
  if (rect.IsEmpty()) {
    return TRUE;
  }
  CFX_Matrix deviceCTM = m_pDevice->GetCTM();
  FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a);
  FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d);
  int width = FXSYS_round((FX_FLOAT)rect.Width() * scaleX);
  int height = FXSYS_round((FX_FLOAT)rect.Height() * scaleY);
  CFX_FxgeDevice bitmap_device;
  nonstd::unique_ptr<CFX_DIBitmap> oriDevice;
  if (!isolated && (m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
    oriDevice.reset(new CFX_DIBitmap);
    if (!m_pDevice->CreateCompatibleBitmap(oriDevice.get(), width, height))
      return TRUE;

    m_pDevice->GetDIBits(oriDevice.get(), rect.left, rect.top);
  }
  if (!bitmap_device.Create(width, height, FXDIB_Argb, 0, oriDevice.get()))
    return TRUE;

  CFX_DIBitmap* bitmap = bitmap_device.GetBitmap();
  bitmap->Clear(0);
  CFX_AffineMatrix new_matrix = *pObj2Device;
  new_matrix.TranslateI(-rect.left, -rect.top);
  new_matrix.Scale(scaleX, scaleY);
  nonstd::unique_ptr<CFX_DIBitmap> pTextMask;
  if (bTextClip) {
    pTextMask.reset(new CFX_DIBitmap);
    if (!pTextMask->Create(width, height, FXDIB_8bppMask))
      return TRUE;

    pTextMask->Clear(0);
    CFX_FxgeDevice text_device;
    text_device.Attach(pTextMask.get());
    for (FX_DWORD i = 0; i < pPageObj->m_ClipPath.GetTextCount(); i++) {
      CPDF_TextObject* textobj = pPageObj->m_ClipPath.GetText(i);
      if (textobj == NULL) {
        break;
      }
      CFX_AffineMatrix text_matrix;
      textobj->GetTextMatrix(&text_matrix);
      CPDF_TextRenderer::DrawTextPath(
          &text_device, textobj->m_nChars, textobj->m_pCharCodes,
          textobj->m_pCharPos, textobj->m_TextState.GetFont(),
          textobj->m_TextState.GetFontSize(), &text_matrix, &new_matrix,
          textobj->m_GraphState, (FX_ARGB)-1, 0, NULL);
    }
  }
  CPDF_RenderStatus bitmap_render;
  bitmap_render.Initialize(m_pContext, &bitmap_device, NULL, m_pStopObj, NULL,
                           NULL, &m_Options, 0, m_bDropObjects, pFormResource,
                           TRUE);
  bitmap_render.ProcessObjectNoClip(pPageObj, &new_matrix);
  m_bStopped = bitmap_render.m_bStopped;
  if (pSMaskDict) {
    CFX_AffineMatrix smask_matrix;
    FXSYS_memcpy(&smask_matrix, pGeneralState->m_SMaskMatrix,
                 sizeof smask_matrix);
    smask_matrix.Concat(*pObj2Device);
    nonstd::unique_ptr<CFX_DIBSource> pSMaskSource(
        LoadSMask(pSMaskDict, &rect, &smask_matrix));
    if (pSMaskSource)
      bitmap->MultiplyAlpha(pSMaskSource.get());
  }
  if (pTextMask) {
    bitmap->MultiplyAlpha(pTextMask.get());
    pTextMask.reset();
  }
  if (Transparency & PDFTRANS_GROUP && group_alpha != 1.0f) {
    bitmap->MultiplyAlpha((int32_t)(group_alpha * 255));
  }
  Transparency = m_Transparency;
  if (pPageObj->m_Type == PDFPAGE_FORM) {
    Transparency |= PDFTRANS_GROUP;
  }
  CompositeDIBitmap(bitmap, rect.left, rect.top, 0, 255, blend_type,
                    Transparency);
  return TRUE;
}
예제 #3
0
bool CPDF_ImageRenderer::StartRenderDIBSource() {
  if (!m_Loader.m_pBitmap)
    return false;

  m_BitmapAlpha =
      FXSYS_round(255 * m_pImageObject->m_GeneralState.GetFillAlpha());
  m_pDIBSource = m_Loader.m_pBitmap;
  if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_ALPHA &&
      !m_Loader.m_pMask) {
    return StartBitmapAlpha();
  }
  if (m_pImageObject->m_GeneralState.GetTR()) {
    if (!m_pImageObject->m_GeneralState.GetTransferFunc()) {
      m_pImageObject->m_GeneralState.SetTransferFunc(
          m_pRenderStatus->GetTransferFunc(
              m_pImageObject->m_GeneralState.GetTR()));
    }
    if (m_pImageObject->m_GeneralState.GetTransferFunc() &&
        !m_pImageObject->m_GeneralState.GetTransferFunc()->m_bIdentity) {
      m_pDIBSource = m_Loader.m_pBitmap =
          m_pImageObject->m_GeneralState.GetTransferFunc()->TranslateImage(
              m_Loader.m_pBitmap, !m_Loader.m_bCached);
      if (m_Loader.m_bCached && m_Loader.m_pMask)
        m_Loader.m_pMask = m_Loader.m_pMask->Clone().release();
      m_Loader.m_bCached = false;
    }
  }
  m_FillArgb = 0;
  m_bPatternColor = false;
  m_pPattern = nullptr;
  if (m_pDIBSource->IsAlphaMask()) {
    const CPDF_Color* pColor = m_pImageObject->m_ColorState.GetFillColor();
    if (pColor && pColor->IsPattern()) {
      m_pPattern = pColor->GetPattern();
      if (m_pPattern)
        m_bPatternColor = true;
    }
    m_FillArgb = m_pRenderStatus->GetFillArgb(m_pImageObject);
  } else if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_GRAY) {
    m_pClone = m_pDIBSource->Clone();
    m_pClone->ConvertColorScale(m_pRenderStatus->m_Options.m_BackColor,
                                m_pRenderStatus->m_Options.m_ForeColor);
    m_pDIBSource = m_pClone.get();
  }
  m_Flags = 0;
  if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_DOWNSAMPLE)
    m_Flags |= RENDER_FORCE_DOWNSAMPLE;
  else if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_HALFTONE)
    m_Flags |= RENDER_FORCE_HALFTONE;
  if (m_pRenderStatus->m_pDevice->GetDeviceClass() != FXDC_DISPLAY) {
    CPDF_Object* pFilters =
        m_pImageObject->GetImage()->GetStream()->GetDict()->GetDirectObjectFor(
            "Filter");
    if (pFilters) {
      if (pFilters->IsName()) {
        CFX_ByteString bsDecodeType = pFilters->GetString();
        if (bsDecodeType == "DCTDecode" || bsDecodeType == "JPXDecode")
          m_Flags |= FXRENDER_IMAGE_LOSSY;
      } else if (CPDF_Array* pArray = pFilters->AsArray()) {
        for (size_t i = 0; i < pArray->GetCount(); i++) {
          CFX_ByteString bsDecodeType = pArray->GetStringAt(i);
          if (bsDecodeType == "DCTDecode" || bsDecodeType == "JPXDecode") {
            m_Flags |= FXRENDER_IMAGE_LOSSY;
            break;
          }
        }
      }
    }
  }
  if (m_pRenderStatus->m_Options.m_Flags & RENDER_NOIMAGESMOOTH)
    m_Flags |= FXDIB_NOSMOOTH;
  else if (m_pImageObject->GetImage()->IsInterpol())
    m_Flags |= FXDIB_INTERPOL;
  if (m_Loader.m_pMask)
    return DrawMaskedImage();

  if (m_bPatternColor)
    return DrawPatternImage(m_pObj2Device);

  if (m_BitmapAlpha != 255 || !m_pImageObject->m_GeneralState ||
      !m_pImageObject->m_GeneralState.GetFillOP() ||
      m_pImageObject->m_GeneralState.GetOPMode() != 0 ||
      m_pImageObject->m_GeneralState.GetBlendType() != FXDIB_BLEND_NORMAL ||
      m_pImageObject->m_GeneralState.GetStrokeAlpha() != 1.0f ||
      m_pImageObject->m_GeneralState.GetFillAlpha() != 1.0f) {
    return StartDIBSource();
  }
  CPDF_Document* pDocument = nullptr;
  CPDF_Page* pPage = nullptr;
  if (m_pRenderStatus->m_pContext->GetPageCache()) {
    pPage = m_pRenderStatus->m_pContext->GetPageCache()->GetPage();
    pDocument = pPage->m_pDocument;
  } else {
    pDocument = m_pImageObject->GetImage()->GetDocument();
  }
  CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : nullptr;
  CPDF_Object* pCSObj =
      m_pImageObject->GetImage()->GetStream()->GetDict()->GetDirectObjectFor(
          "ColorSpace");
  CPDF_ColorSpace* pColorSpace =
      pDocument->LoadColorSpace(pCSObj, pPageResources);
  if (!pColorSpace)
    return StartDIBSource();
  int format = pColorSpace->GetFamily();
  if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION ||
      format == PDFCS_DEVICEN) {
    m_BlendType = FXDIB_BLEND_DARKEN;
  }
  pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
  return StartDIBSource();
}
예제 #4
0
FX_BOOL CPDF_ImageRenderer::StartRenderDIBSource() {
    if (m_Loader.m_pBitmap == NULL) {
        return FALSE;
    }
    m_BitmapAlpha = 255;
    const CPDF_GeneralStateData* pGeneralState = m_pImageObject->m_GeneralState;
    if (pGeneralState) {
        m_BitmapAlpha = FXSYS_round(pGeneralState->m_FillAlpha * 255);
    }
    m_pDIBSource = m_Loader.m_pBitmap;
    if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_ALPHA &&
            m_Loader.m_pMask == NULL) {
        return StartBitmapAlpha();
    }
    if (pGeneralState && pGeneralState->m_pTR) {
        if (!pGeneralState->m_pTransferFunc) {
            ((CPDF_GeneralStateData*)pGeneralState)->m_pTransferFunc =
                m_pRenderStatus->GetTransferFunc(pGeneralState->m_pTR);
        }
        if (pGeneralState->m_pTransferFunc &&
                !pGeneralState->m_pTransferFunc->m_bIdentity) {
            m_pDIBSource = m_Loader.m_pBitmap =
                               pGeneralState->m_pTransferFunc->TranslateImage(m_Loader.m_pBitmap,
                                       !m_Loader.m_bCached);
            if (m_Loader.m_bCached && m_Loader.m_pMask) {
                m_Loader.m_pMask = m_Loader.m_pMask->Clone();
            }
            m_Loader.m_bCached = FALSE;
        }
    }
    m_FillArgb = 0;
    m_bPatternColor = FALSE;
    m_pPattern = NULL;
    if (m_pDIBSource->IsAlphaMask()) {
        CPDF_Color* pColor = m_pImageObject->m_ColorState.GetFillColor();
        if (pColor && pColor->IsPattern()) {
            m_pPattern = pColor->GetPattern();
            if (m_pPattern != NULL) {
                m_bPatternColor = TRUE;
            }
        }
        m_FillArgb = m_pRenderStatus->GetFillArgb(m_pImageObject);
    } else if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_GRAY) {
        m_pClone = m_pDIBSource->Clone();
        m_pClone->ConvertColorScale(m_pRenderStatus->m_Options.m_BackColor,
                                    m_pRenderStatus->m_Options.m_ForeColor);
        m_pDIBSource = m_pClone;
    }
    m_Flags = 0;
    if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_DOWNSAMPLE) {
        m_Flags |= RENDER_FORCE_DOWNSAMPLE;
    } else if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_HALFTONE) {
        m_Flags |= RENDER_FORCE_HALFTONE;
    }
    if (m_pRenderStatus->m_pDevice->GetDeviceClass() != FXDC_DISPLAY) {
        CPDF_Object* pFilters =
            m_pImageObject->m_pImage->GetStream()->GetDict()->GetElementValue(
                FX_BSTRC("Filter"));
        if (pFilters) {
            if (pFilters->IsName()) {
                CFX_ByteStringC bsDecodeType = pFilters->GetConstString();
                if (bsDecodeType == FX_BSTRC("DCTDecode") ||
                        bsDecodeType == FX_BSTRC("JPXDecode")) {
                    m_Flags |= FXRENDER_IMAGE_LOSSY;
                }
            } else if (CPDF_Array* pArray = pFilters->AsArray()) {
                for (FX_DWORD i = 0; i < pArray->GetCount(); i++) {
                    CFX_ByteStringC bsDecodeType = pArray->GetConstString(i);
                    if (bsDecodeType == FX_BSTRC("DCTDecode") ||
                            bsDecodeType == FX_BSTRC("JPXDecode")) {
                        m_Flags |= FXRENDER_IMAGE_LOSSY;
                        break;
                    }
                }
            }
        }
    }
    if (m_pRenderStatus->m_Options.m_Flags & RENDER_NOIMAGESMOOTH) {
        m_Flags |= FXDIB_NOSMOOTH;
    } else if (m_pImageObject->m_pImage->IsInterpol()) {
        m_Flags |= FXDIB_INTERPOL;
    }
    if (m_Loader.m_pMask) {
        return DrawMaskedImage();
    }
    if (m_bPatternColor) {
        return DrawPatternImage(m_pObj2Device);
    }
    if (m_BitmapAlpha == 255 && pGeneralState && pGeneralState->m_FillOP &&
            pGeneralState->m_OPMode == 0 &&
            pGeneralState->m_BlendType == FXDIB_BLEND_NORMAL &&
            pGeneralState->m_StrokeAlpha == 1 && pGeneralState->m_FillAlpha == 1) {
        CPDF_Document* pDocument = NULL;
        CPDF_Page* pPage = NULL;
        if (m_pRenderStatus->m_pContext->m_pPageCache) {
            pPage = m_pRenderStatus->m_pContext->m_pPageCache->GetPage();
            pDocument = pPage->m_pDocument;
        } else {
            pDocument = m_pImageObject->m_pImage->GetDocument();
        }
        CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : NULL;
        CPDF_Object* pCSObj =
            m_pImageObject->m_pImage->GetStream()->GetDict()->GetElementValue(
                FX_BSTRC("ColorSpace"));
        CPDF_ColorSpace* pColorSpace =
            pDocument->LoadColorSpace(pCSObj, pPageResources);
        if (pColorSpace) {
            int format = pColorSpace->GetFamily();
            if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION ||
                    format == PDFCS_DEVICEN) {
                m_BlendType = FXDIB_BLEND_DARKEN;
            }
            pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
        }
    }
    return StartDIBSource();
}
예제 #5
0
CFX_DIBitmap* CPDF_RenderStatus::LoadSMask(CPDF_Dictionary* pSMaskDict,
        FX_RECT* pClipRect,
        const CFX_AffineMatrix* pMatrix) {
    if (pSMaskDict == NULL) {
        return NULL;
    }
    int width = pClipRect->right - pClipRect->left;
    int height = pClipRect->bottom - pClipRect->top;
    FX_BOOL bLuminosity = FALSE;
    bLuminosity = pSMaskDict->GetConstString(FX_BSTRC("S")) != FX_BSTRC("Alpha");
    CPDF_Stream* pGroup = pSMaskDict->GetStream(FX_BSTRC("G"));
    if (pGroup == NULL) {
        return NULL;
    }
    nonstd::unique_ptr<CPDF_Function> pFunc;
    CPDF_Object* pFuncObj = pSMaskDict->GetElementValue(FX_BSTRC("TR"));
    if (pFuncObj && (pFuncObj->IsDictionary() || pFuncObj->IsStream()))
        pFunc.reset(CPDF_Function::Load(pFuncObj));

    CFX_AffineMatrix matrix = *pMatrix;
    matrix.TranslateI(-pClipRect->left, -pClipRect->top);
    CPDF_Form form(m_pContext->m_pDocument, m_pContext->m_pPageResources, pGroup);
    form.ParseContent(NULL, NULL, NULL, NULL);
    CFX_FxgeDevice bitmap_device;
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
    if (!bitmap_device.Create(width, height,
                              bLuminosity ? FXDIB_Rgb32 : FXDIB_8bppMask)) {
        return NULL;
    }
#else
    if (!bitmap_device.Create(width, height,
                              bLuminosity ? FXDIB_Rgb : FXDIB_8bppMask)) {
        return NULL;
    }
#endif
    CFX_DIBitmap& bitmap = *bitmap_device.GetBitmap();
    CPDF_Object* pCSObj = NULL;
    CPDF_ColorSpace* pCS = NULL;
    if (bLuminosity) {
        CPDF_Array* pBC = pSMaskDict->GetArray(FX_BSTRC("BC"));
        FX_ARGB back_color = 0xff000000;
        if (pBC) {
            CPDF_Dictionary* pDict = pGroup->GetDict();
            if (pDict && pDict->GetDict(FX_BSTRC("Group")))
                pCSObj =
                    pDict->GetDict(FX_BSTRC("Group"))->GetElementValue(FX_BSTRC("CS"));
            else
                pCSObj = NULL;
            pCS = m_pContext->m_pDocument->LoadColorSpace(pCSObj);
            if (pCS) {
                FX_FLOAT R, G, B;
                FX_DWORD comps = 8;
                if (pCS->CountComponents() > static_cast<int32_t>(comps)) {
                    comps = (FX_DWORD)pCS->CountComponents();
                }
                CFX_FixedBufGrow<FX_FLOAT, 8> float_array(comps);
                FX_FLOAT* pFloats = float_array;
                FX_SAFE_DWORD num_floats = comps;
                num_floats *= sizeof(FX_FLOAT);
                if (!num_floats.IsValid()) {
                    return NULL;
                }
                FXSYS_memset(pFloats, 0, num_floats.ValueOrDie());
                int count = pBC->GetCount() > 8 ? 8 : pBC->GetCount();
                for (int i = 0; i < count; i++) {
                    pFloats[i] = pBC->GetNumber(i);
                }
                pCS->GetRGB(pFloats, R, G, B);
                back_color = 0xff000000 | ((int32_t)(R * 255) << 16) |
                             ((int32_t)(G * 255) << 8) | (int32_t)(B * 255);
                m_pContext->m_pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
            }
        }
        bitmap.Clear(back_color);
    } else {
        bitmap.Clear(0);
    }
    CPDF_Dictionary* pFormResource = NULL;
    if (form.m_pFormDict) {
        pFormResource = form.m_pFormDict->GetDict(FX_BSTRC("Resources"));
    }
    CPDF_RenderOptions options;
    options.m_ColorMode = bLuminosity ? RENDER_COLOR_NORMAL : RENDER_COLOR_ALPHA;
    CPDF_RenderStatus status;
    status.Initialize(m_pContext, &bitmap_device, NULL, NULL, NULL, NULL,
                      &options, 0, m_bDropObjects, pFormResource, TRUE, NULL, 0,
                      pCS ? pCS->GetFamily() : 0, bLuminosity);
    status.RenderObjectList(&form, &matrix);
    nonstd::unique_ptr<CFX_DIBitmap> pMask(new CFX_DIBitmap);
    if (!pMask->Create(width, height, FXDIB_8bppMask))
        return nullptr;

    uint8_t* dest_buf = pMask->GetBuffer();
    int dest_pitch = pMask->GetPitch();
    uint8_t* src_buf = bitmap.GetBuffer();
    int src_pitch = bitmap.GetPitch();
    std::vector<uint8_t> transfers(256);
    if (pFunc) {
        CFX_FixedBufGrow<FX_FLOAT, 16> results(pFunc->CountOutputs());
        for (int i = 0; i < 256; i++) {
            FX_FLOAT input = (FX_FLOAT)i / 255.0f;
            int nresult;
            pFunc->Call(&input, 1, results, nresult);
            transfers[i] = FXSYS_round(results[0] * 255);
        }
    } else {
        for (int i = 0; i < 256; i++) {
            transfers[i] = i;
        }
    }
    if (bLuminosity) {
        int Bpp = bitmap.GetBPP() / 8;
        for (int row = 0; row < height; row++) {
            uint8_t* dest_pos = dest_buf + row * dest_pitch;
            uint8_t* src_pos = src_buf + row * src_pitch;
            for (int col = 0; col < width; col++) {
                *dest_pos++ = transfers[FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos)];
                src_pos += Bpp;
            }
        }
    } else if (pFunc) {
        int size = dest_pitch * height;
        for (int i = 0; i < size; i++) {
            dest_buf[i] = transfers[src_buf[i]];
        }
    } else {
        FXSYS_memcpy(dest_buf, src_buf, dest_pitch * height);
    }
    return pMask.release();
}
CFX_DIBitmap* CPDF_RenderStatus::LoadSMask(CPDF_Dictionary* pSMaskDict,
        FX_RECT* pClipRect, const CFX_AffineMatrix* pMatrix)
{
    if (pSMaskDict == NULL) {
        return NULL;
    }
    CFX_DIBitmap* pMask = NULL;
    int width = pClipRect->right - pClipRect->left;
    int height = pClipRect->bottom - pClipRect->top;
    FX_BOOL bLuminosity = FALSE;
    bLuminosity = pSMaskDict->GetConstString(FX_BSTRC("S")) != FX_BSTRC("Alpha");
    CPDF_Stream* pGroup = pSMaskDict->GetStream(FX_BSTRC("G"));
    if (pGroup == NULL) {
        return NULL;
    }
    CPDF_Function* pFunc = NULL;
    CPDF_Object* pFuncObj = pSMaskDict->GetElementValue(FX_BSTRC("TR"));
    if (pFuncObj && (pFuncObj->GetType() == PDFOBJ_DICTIONARY || pFuncObj->GetType() == PDFOBJ_STREAM)) {
        pFunc = CPDF_Function::Load(pFuncObj);
    }
    CFX_AffineMatrix matrix = *pMatrix;
    matrix.TranslateI(-pClipRect->left, -pClipRect->top);
    CPDF_Form form(m_pContext->m_pDocument, m_pContext->m_pPageResources, pGroup);
    form.ParseContent(NULL, NULL, NULL, NULL);
    CFX_FxgeDevice bitmap_device;
#if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_
    if (!bitmap_device.Create(width, height, bLuminosity ? FXDIB_Rgb32 : FXDIB_8bppMask)) {
        return NULL;
    }
#else
    if (!bitmap_device.Create(width, height, bLuminosity ? FXDIB_Rgb : FXDIB_8bppMask)) {
        return NULL;
    }
#endif
    CFX_DIBitmap& bitmap = *bitmap_device.GetBitmap();
    CPDF_Object* pCSObj = NULL;
    CPDF_ColorSpace* pCS = NULL;
    if (bLuminosity) {
        CPDF_Array* pBC = pSMaskDict->GetArray(FX_BSTRC("BC"));
        FX_ARGB back_color = 0xff000000;
        if (pBC) {
            pCSObj = pGroup->GetDict()->GetDict(FX_BSTRC("Group"))->GetElementValue(FX_BSTRC("CS"));
            pCS = m_pContext->m_pDocument->LoadColorSpace(pCSObj);
            if (pCS) {
                FX_FLOAT R, G, B;
                FX_DWORD num_floats = 8;
                if (pCS->CountComponents() > (FX_INT32)num_floats) {
                    num_floats = (FX_DWORD)pCS->CountComponents();
                }
                CFX_FixedBufGrow<FX_FLOAT, 8> float_array(num_floats);
                FX_FLOAT* pFloats = float_array;
                FXSYS_memset32(pFloats, 0, num_floats * sizeof(FX_FLOAT));
                int count = pBC->GetCount() > 8 ? 8 : pBC->GetCount();
                for (int i = 0; i < count; i ++) {
                    pFloats[i] = pBC->GetNumber(i);
                }
                pCS->GetRGB(pFloats, R, G, B);
                back_color = 0xff000000 | ((FX_INT32)(R * 255) << 16) | ((FX_INT32)(G * 255) << 8) | (FX_INT32)(B * 255);
                m_pContext->m_pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
            }
        }
        bitmap.Clear(back_color);
    } else {
        bitmap.Clear(0);
    }
    CPDF_Dictionary* pFormResource = NULL;
    if (form.m_pFormDict) {
        pFormResource = form.m_pFormDict->GetDict(FX_BSTRC("Resources"));
    }
    CPDF_RenderOptions options;
    options.m_ColorMode = bLuminosity ? RENDER_COLOR_NORMAL : RENDER_COLOR_ALPHA;
    CPDF_RenderStatus status;
    status.Initialize(m_Level + 1, m_pContext, &bitmap_device, NULL, NULL, NULL, NULL,
                      &options, 0, m_bDropObjects, pFormResource, TRUE, NULL, 0, pCS ? pCS->GetFamily() : 0, bLuminosity);
    status.RenderObjectList(&form, &matrix);
    pMask = FX_NEW CFX_DIBitmap;
    if (!pMask->Create(width, height, FXDIB_8bppMask)) {
        delete pMask;
        return NULL;
    }
    FX_LPBYTE dest_buf = pMask->GetBuffer();
    int dest_pitch = pMask->GetPitch();
    FX_LPBYTE src_buf = bitmap.GetBuffer();
    int src_pitch = bitmap.GetPitch();
    FX_LPBYTE pTransfer = FX_Alloc(FX_BYTE, 256);
    if (pFunc) {
        CFX_FixedBufGrow<FX_FLOAT, 16> results(pFunc->CountOutputs());
        for (int i = 0; i < 256; i ++) {
            FX_FLOAT input = (FX_FLOAT)i / 255.0f;
            int nresult;
            pFunc->Call(&input, 1, results, nresult);
            pTransfer[i] = FXSYS_round(results[0] * 255);
        }
    } else {
        for (int i = 0; i < 256; i ++) {
            pTransfer[i] = i;
        }
    }
    if (bLuminosity) {
        int Bpp = bitmap.GetBPP() / 8;
        for (int row = 0; row < height; row ++) {
            FX_LPBYTE dest_pos = dest_buf + row * dest_pitch;
            FX_LPBYTE src_pos = src_buf + row * src_pitch;
            for (int col = 0; col < width; col ++) {
                *dest_pos ++ = pTransfer[FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos)];
                src_pos += Bpp;
            }
        }
    } else if (pFunc) {
        int size = dest_pitch * height;
        for (int i = 0; i < size; i ++) {
            dest_buf[i] = pTransfer[src_buf[i]];
        }
    } else {
        FXSYS_memcpy32(dest_buf, src_buf, dest_pitch * height);
    }
    if (pFunc) {
        delete pFunc;
    }
    FX_Free(pTransfer);
    return pMask;
}
예제 #7
0
CPDF_ColorSpace* CPDF_DocPageData::GetColorSpace(
    CPDF_Object* pCSObj,
    const CPDF_Dictionary* pResources) {
  if (!pCSObj)
    return nullptr;

  if (pCSObj->IsName()) {
    CFX_ByteString name = pCSObj->GetConstString();
    CPDF_ColorSpace* pCS = _CSFromName(name);
    if (!pCS && pResources) {
      CPDF_Dictionary* pList = pResources->GetDictBy("ColorSpace");
      if (pList) {
        pCSObj = pList->GetElementValue(name);
        return GetColorSpace(pCSObj, nullptr);
      }
    }
    if (!pCS || !pResources)
      return pCS;

    CPDF_Dictionary* pColorSpaces = pResources->GetDictBy("ColorSpace");
    if (!pColorSpaces)
      return pCS;

    CPDF_Object* pDefaultCS = nullptr;
    switch (pCS->GetFamily()) {
      case PDFCS_DEVICERGB:
        pDefaultCS = pColorSpaces->GetElementValue("DefaultRGB");
        break;
      case PDFCS_DEVICEGRAY:
        pDefaultCS = pColorSpaces->GetElementValue("DefaultGray");
        break;
      case PDFCS_DEVICECMYK:
        pDefaultCS = pColorSpaces->GetElementValue("DefaultCMYK");
        break;
    }
    return pDefaultCS ? GetColorSpace(pDefaultCS, nullptr) : pCS;
  }

  CPDF_Array* pArray = pCSObj->AsArray();
  if (!pArray || pArray->GetCount() == 0)
    return nullptr;
  if (pArray->GetCount() == 1)
    return GetColorSpace(pArray->GetElementValue(0), pResources);

  CPDF_CountedColorSpace* csData = nullptr;
  auto it = m_ColorSpaceMap.find(pCSObj);
  if (it != m_ColorSpaceMap.end()) {
    csData = it->second;
    if (csData->get()) {
      return csData->AddRef();
    }
  }

  CPDF_ColorSpace* pCS = CPDF_ColorSpace::Load(m_pPDFDoc, pArray);
  if (!pCS)
    return nullptr;

  if (!csData) {
    csData = new CPDF_CountedColorSpace(pCS);
    m_ColorSpaceMap[pCSObj] = csData;
  } else {
    csData->reset(pCS);
  }
  return csData->AddRef();
}
예제 #8
0
CPDF_ColorSpace* CPDF_DocPageData::GetColorSpace(CPDF_Object* pCSObj, CPDF_Dictionary* pResources)
{
    if (!pCSObj) {
        return NULL;
    }
    if (pCSObj->GetType() == PDFOBJ_NAME) {
        CFX_ByteString name = pCSObj->GetConstString();
        CPDF_ColorSpace* pCS = _CSFromName(name);
        if (!pCS && pResources) {
            CPDF_Dictionary* pList = pResources->GetDict(FX_BSTRC("ColorSpace"));
            if (pList) {
                pCSObj = pList->GetElementValue(name);
                return GetColorSpace(pCSObj, NULL);
            }
        }
        if (pCS == NULL || pResources == NULL) {
            return pCS;
        }
        CPDF_Dictionary* pColorSpaces = pResources->GetDict(FX_BSTRC("ColorSpace"));
        if (pColorSpaces == NULL) {
            return pCS;
        }
        CPDF_Object* pDefaultCS = NULL;
        switch (pCS->GetFamily()) {
        case PDFCS_DEVICERGB:
            pDefaultCS = pColorSpaces->GetElementValue(FX_BSTRC("DefaultRGB"));
            break;
        case PDFCS_DEVICEGRAY:
            pDefaultCS = pColorSpaces->GetElementValue(FX_BSTRC("DefaultGray"));
            break;
        case PDFCS_DEVICECMYK:
            pDefaultCS = pColorSpaces->GetElementValue(FX_BSTRC("DefaultCMYK"));
            break;
        }
        if (pDefaultCS == NULL) {
            return pCS;
        }
        return GetColorSpace(pDefaultCS, NULL);
    }
    if (pCSObj->GetType() != PDFOBJ_ARRAY) {
        return NULL;
    }
    CPDF_Array* pArray = (CPDF_Array*)pCSObj;
    if (pArray->GetCount() == 0) {
        return NULL;
    }
    if (pArray->GetCount() == 1) {
        return GetColorSpace(pArray->GetElementValue(0), pResources);
    }
    CPDF_CountedObject<CPDF_ColorSpace*>* csData = NULL;
    if (m_ColorSpaceMap.Lookup(pCSObj, csData)) {
        if (csData->m_Obj) {
            csData->m_nCount++;
            return csData->m_Obj;
        }
    }
    FX_BOOL bNew = FALSE;
    if (!csData) {
        csData = FX_NEW CPDF_CountedObject<CPDF_ColorSpace*>;
        if (!csData) {
            return NULL;
        }
        bNew = TRUE;
    }
    CPDF_ColorSpace* pCS = CPDF_ColorSpace::Load(m_pPDFDoc, pArray);
    if (!pCS) {
        if (bNew) {
            delete csData;
        }
        return NULL;
    }
    csData->m_nCount = 2;
    csData->m_Obj = pCS;
    m_ColorSpaceMap.SetAt(pCSObj, csData);
    return pCS;
}