FX_BOOL CPDF_IndexedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { if (pArray->GetCount() < 4) { return FALSE; } CPDF_Object* pBaseObj = pArray->GetElementValue(1); if (pBaseObj == m_pArray) { return FALSE; } CPDF_DocPageData* pDocPageData = pDoc->GetPageData(); m_pBaseCS = pDocPageData->GetColorSpace(pBaseObj, NULL); if (m_pBaseCS == NULL) { return FALSE; } m_nBaseComponents = m_pBaseCS->CountComponents(); m_pCompMinMax = FX_Alloc(FX_FLOAT, m_nBaseComponents * 2); FX_FLOAT defvalue; for (int i = 0; i < m_nBaseComponents; i ++) { m_pBaseCS->GetDefaultValue(i, defvalue, m_pCompMinMax[i * 2], m_pCompMinMax[i * 2 + 1]); m_pCompMinMax[i * 2 + 1] -= m_pCompMinMax[i * 2]; } m_MaxIndex = pArray->GetInteger(2); CPDF_Object* pTableObj = pArray->GetElementValue(3); if (pTableObj == NULL) { return FALSE; } if (pTableObj->GetType() == PDFOBJ_STRING) { m_Table = ((CPDF_String*)pTableObj)->GetString(); } else if (pTableObj->GetType() == PDFOBJ_STREAM) { CPDF_StreamAcc acc; acc.LoadAllData((CPDF_Stream*)pTableObj, FALSE); m_Table = CFX_ByteStringC(acc.GetData(), acc.GetSize()); } return TRUE; }
FX_BOOL CPDF_SeparationCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const { if (m_Type == None) { return FALSE; } if (m_pFunc == NULL) { if (m_pAltCS == NULL) { return FALSE; } int nComps = m_pAltCS->CountComponents(); CFX_FixedBufGrow<FX_FLOAT, 16> results(nComps); for (int i = 0; i < nComps; i ++) { results[i] = *pBuf; } m_pAltCS->GetRGB(results, R, G, B); return TRUE; } CFX_FixedBufGrow<FX_FLOAT, 16> results(m_pFunc->CountOutputs()); int nresults = 0; m_pFunc->Call(pBuf, 1, results, nresults); if (nresults == 0) { return FALSE; } if (m_pAltCS) { m_pAltCS->GetRGB(results, R, G, B); return TRUE; } R = G = B = 0; return FALSE; }
CPDF_IndexedCS::~CPDF_IndexedCS() { FX_Free(m_pCompMinMax); CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->get() : NULL; if (pCS && m_pDocument) { m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray()); } }
CPDF_PatternCS::~CPDF_PatternCS() { CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->get() : NULL; if (pCS && m_pDocument) { m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray()); } }
CPDF_DIBSource::~CPDF_DIBSource() { FX_Free(m_pMaskedLine); FX_Free(m_pLineBuf); m_pCachedBitmap.reset(); FX_Free(m_pCompData); CPDF_ColorSpace* pCS = m_pColorSpace; if (pCS && m_pDocument) { m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray()); } }
void CPDF_ShadingPattern::Clear() { for (int i = 0; i < m_nFuncs; i ++) { if (m_pFunctions[i]) { delete m_pFunctions[i]; } m_pFunctions[i] = NULL; } CPDF_ColorSpace* pCS = m_pCS; if (pCS && m_pDocument) { m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray()); } m_ShadingType = 0; m_pCS = NULL; m_nFuncs = 0; }
void CPDF_ICCBasedCS::EnableStdConversion(FX_BOOL bEnabled) { CPDF_ColorSpace::EnableStdConversion(bEnabled); if (m_pAlterCS) { m_pAlterCS->EnableStdConversion(bEnabled); } }
void CPDF_IndexedCS::EnableStdConversion(FX_BOOL bEnabled) { CPDF_ColorSpace::EnableStdConversion(bEnabled); if (m_pBaseCS) { m_pBaseCS->EnableStdConversion(bEnabled); } }
FX_BOOL CPDF_SeparationCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { CFX_ByteString name = pArray->GetString(1); if (name == FX_BSTRC("None")) { m_Type = None; } else { m_Type = Colorant; CPDF_Object* pAltCS = pArray->GetElementValue(2); if (pAltCS == m_pArray) { return FALSE; } m_pAltCS = Load(pDoc, pAltCS); if (!m_pAltCS) { return FALSE; } CPDF_Object* pFuncObj = pArray->GetElementValue(3); if (pFuncObj && pFuncObj->GetType() != PDFOBJ_NAME) { m_pFunc = CPDF_Function::Load(pFuncObj); } if (m_pFunc && m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) { delete m_pFunc; m_pFunc = NULL; } } return TRUE; }
FX_BOOL CPDF_IndexedCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const { int index = (int32_t)(*pBuf); if (index < 0 || index > m_MaxIndex) { return FALSE; } if (m_nBaseComponents) { if (index == INT_MAX || (index + 1) > INT_MAX / m_nBaseComponents || (index + 1) * m_nBaseComponents > (int)m_Table.GetLength()) { R = G = B = 0; return FALSE; } } CFX_FixedBufGrow<FX_FLOAT, 16> Comps(m_nBaseComponents); FX_FLOAT* comps = Comps; const uint8_t* pTable = m_Table; for (int i = 0; i < m_nBaseComponents; i++) { comps[i] = m_pCompMinMax[i * 2] + m_pCompMinMax[i * 2 + 1] * pTable[index * m_nBaseComponents + i] / 255; } m_pBaseCS->GetRGB(comps, R, G, B); return TRUE; }
FX_BOOL CPDF_ICCBasedCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const { if (m_pProfile && m_pProfile->m_bsRGB) { R = pBuf[0]; G = pBuf[1]; B = pBuf[2]; return TRUE; } ICodec_IccModule *pIccModule = CPDF_ModuleMgr::Get()->GetIccModule(); if (m_pProfile->m_pTransform == NULL || pIccModule == NULL) { if (m_pAlterCS) { m_pAlterCS->GetRGB(pBuf, R, G, B); } else { R = G = B = 0.0f; } return TRUE; } FX_FLOAT rgb[3]; pIccModule->SetComponents(m_nComponents); pIccModule->Translate(m_pProfile->m_pTransform, pBuf, rgb); R = rgb[0]; G = rgb[1]; B = rgb[2]; return TRUE; }
void CPDF_SeparationCS::EnableStdConversion(FX_BOOL bEnabled) { CPDF_ColorSpace::EnableStdConversion(bEnabled); if (m_pAltCS) { m_pAltCS->EnableStdConversion(bEnabled); } }
void CPDF_ICCBasedCS::TranslateImageLine(uint8_t* pDestBuf, const uint8_t* pSrcBuf, int pixels, int image_width, int image_height, FX_BOOL bTransMask) const { if (m_pProfile->m_bsRGB) { ReverseRGB(pDestBuf, pSrcBuf, pixels); } else if (m_pProfile->m_pTransform) { int nMaxColors = 1; for (int i = 0; i < m_nComponents; i++) { nMaxColors *= 52; } if (m_nComponents > 3 || image_width * image_height < nMaxColors * 3 / 2) { CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline( m_pProfile->m_pTransform, pDestBuf, pSrcBuf, pixels); } else { if (m_pCache == NULL) { ((CPDF_ICCBasedCS*)this)->m_pCache = FX_Alloc2D(uint8_t, nMaxColors, 3); uint8_t* temp_src = FX_Alloc2D(uint8_t, nMaxColors, m_nComponents); uint8_t* pSrc = temp_src; for (int i = 0; i < nMaxColors; i++) { FX_DWORD color = i; FX_DWORD order = nMaxColors / 52; for (int c = 0; c < m_nComponents; c++) { *pSrc++ = (uint8_t)(color / order * 5); color %= order; order /= 52; } } CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline( m_pProfile->m_pTransform, m_pCache, temp_src, nMaxColors); FX_Free(temp_src); } for (int i = 0; i < pixels; i++) { int index = 0; for (int c = 0; c < m_nComponents; c++) { index = index * 52 + (*pSrcBuf) / 5; pSrcBuf++; } index *= 3; *pDestBuf++ = m_pCache[index]; *pDestBuf++ = m_pCache[index + 1]; *pDestBuf++ = m_pCache[index + 2]; } } } else if (m_pAlterCS) { m_pAlterCS->TranslateImageLine(pDestBuf, pSrcBuf, pixels, image_width, image_height); } }
FX_BOOL CPDF_DeviceNCS::GetRGB(FX_FLOAT* pBuf, FX_FLOAT& R, FX_FLOAT& G, FX_FLOAT& B) const { if (m_pFunc == NULL) { return FALSE; } CFX_FixedBufGrow<FX_FLOAT, 16> results(m_pFunc->CountOutputs()); int nresults = 0; m_pFunc->Call(pBuf, m_nComponents, results, nresults); if (nresults == 0) { return FALSE; } m_pAltCS->GetRGB(results, R, G, B); return TRUE; }
FX_BOOL CPDF_IndexedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { if (pArray->GetCount() < 4) { return FALSE; } CPDF_Object* pBaseObj = pArray->GetElementValue(1); if (pBaseObj == m_pArray) { return FALSE; } CPDF_DocPageData* pDocPageData = pDoc->GetPageData(); m_pBaseCS = pDocPageData->GetColorSpace(pBaseObj, NULL); if (!m_pBaseCS) { return FALSE; } m_pCountedBaseCS = pDocPageData->FindColorSpacePtr(m_pBaseCS->GetArray()); m_nBaseComponents = m_pBaseCS->CountComponents(); m_pCompMinMax = FX_Alloc2D(FX_FLOAT, m_nBaseComponents, 2); FX_FLOAT defvalue; for (int i = 0; i < m_nBaseComponents; i++) { m_pBaseCS->GetDefaultValue(i, defvalue, m_pCompMinMax[i * 2], m_pCompMinMax[i * 2 + 1]); m_pCompMinMax[i * 2 + 1] -= m_pCompMinMax[i * 2]; } m_MaxIndex = pArray->GetInteger(2); CPDF_Object* pTableObj = pArray->GetElementValue(3); if (!pTableObj) return FALSE; if (CPDF_String* pString = pTableObj->AsString()) { m_Table = pString->GetString(); } else if (CPDF_Stream* pStream = pTableObj->AsStream()) { CPDF_StreamAcc acc; acc.LoadAllData(pStream, FALSE); m_Table = CFX_ByteStringC(acc.GetData(), acc.GetSize()); } return TRUE; }
FX_BOOL CPDF_DeviceNCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { CPDF_Array* pObj = ToArray(pArray->GetElementValue(1)); if (!pObj) return FALSE; m_nComponents = pObj->GetCount(); CPDF_Object* pAltCS = pArray->GetElementValue(2); if (!pAltCS || pAltCS == m_pArray) { return FALSE; } m_pAltCS = Load(pDoc, pAltCS); m_pFunc = CPDF_Function::Load(pArray->GetElementValue(3)); if (!m_pAltCS || !m_pFunc) { return FALSE; } if (m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) { return FALSE; } return TRUE; }
FX_BOOL CPDF_DeviceNCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { CPDF_Object* pObj = pArray->GetElementValue(1); if (!pObj) { return FALSE; } if (pObj->GetType() != PDFOBJ_ARRAY) { return FALSE; } m_nComponents = ((CPDF_Array*)pObj)->GetCount(); CPDF_Object* pAltCS = pArray->GetElementValue(2); if (!pAltCS || pAltCS == m_pArray) { return FALSE; } m_pAltCS = Load(pDoc, pAltCS); m_pFunc = CPDF_Function::Load(pArray->GetElementValue(3)); if (m_pAltCS == NULL || m_pFunc == NULL) { return FALSE; } if (m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) { return FALSE; } return TRUE; }
std::unique_ptr<CPDF_Stream> CPDF_StreamParser::ReadInlineStream( CPDF_Document* pDoc, std::unique_ptr<CPDF_Dictionary> pDict, const CPDF_Object* pCSObj) { if (m_Pos < m_pBuf.size() && PDFCharIsWhitespace(m_pBuf[m_Pos])) m_Pos++; if (m_Pos == m_pBuf.size()) return nullptr; ByteString Decoder; CPDF_Dictionary* pParam = nullptr; CPDF_Object* pFilter = pDict->GetDirectObjectFor("Filter"); if (pFilter) { if (CPDF_Array* pArray = pFilter->AsArray()) { Decoder = pArray->GetStringAt(0); CPDF_Array* pParams = pDict->GetArrayFor(pdfium::stream::kDecodeParms); if (pParams) pParam = pParams->GetDictAt(0); } else { Decoder = pFilter->GetString(); pParam = pDict->GetDictFor(pdfium::stream::kDecodeParms); } } uint32_t width = pDict->GetIntegerFor("Width"); uint32_t height = pDict->GetIntegerFor("Height"); uint32_t OrigSize = 0; if (pCSObj) { uint32_t bpc = pDict->GetIntegerFor("BitsPerComponent"); uint32_t nComponents = 1; CPDF_ColorSpace* pCS = pDoc->LoadColorSpace(pCSObj, nullptr); if (pCS) { nComponents = pCS->CountComponents(); pDoc->GetPageData()->ReleaseColorSpace(pCSObj); } else { nComponents = 3; } uint32_t pitch = width; if (bpc && pitch > INT_MAX / bpc) return nullptr; pitch *= bpc; if (nComponents && pitch > INT_MAX / nComponents) return nullptr; pitch *= nComponents; if (pitch > INT_MAX - 7) return nullptr; pitch += 7; pitch /= 8; OrigSize = pitch; } else { if (width > INT_MAX - 7) return nullptr; OrigSize = ((width + 7) / 8); } if (height && OrigSize > INT_MAX / height) return nullptr; OrigSize *= height; std::unique_ptr<uint8_t, FxFreeDeleter> pData; uint32_t dwStreamSize; if (Decoder.IsEmpty()) { if (OrigSize > m_pBuf.size() - m_Pos) OrigSize = m_pBuf.size() - m_Pos; pData.reset(FX_Alloc(uint8_t, OrigSize)); auto copy_span = m_pBuf.subspan(m_Pos, OrigSize); memcpy(pData.get(), copy_span.data(), copy_span.size()); dwStreamSize = OrigSize; m_Pos += OrigSize; } else { dwStreamSize = DecodeInlineStream(m_pBuf.subspan(m_Pos), width, height, Decoder, pParam, OrigSize); if (static_cast<int>(dwStreamSize) < 0) return nullptr; uint32_t dwSavePos = m_Pos; m_Pos += dwStreamSize; while (1) { uint32_t dwPrevPos = m_Pos; CPDF_StreamParser::SyntaxType type = ParseNextElement(); if (type == CPDF_StreamParser::EndOfData) break; if (type != CPDF_StreamParser::Keyword) { dwStreamSize += m_Pos - dwPrevPos; continue; } if (GetWord() == "EI") { m_Pos = dwPrevPos; break; } dwStreamSize += m_Pos - dwPrevPos; } m_Pos = dwSavePos; pData.reset(FX_Alloc(uint8_t, dwStreamSize)); auto copy_span = m_pBuf.subspan(m_Pos, dwStreamSize); memcpy(pData.get(), copy_span.data(), copy_span.size()); m_Pos += dwStreamSize; } pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(dwStreamSize)); return pdfium::MakeUnique<CPDF_Stream>(std::move(pData), dwStreamSize, std::move(pDict)); }
void CPDF_StreamContentParser::EndImageDict() { if (m_StringBuf.GetSize() != m_LastImageDict.GetSize() || FXSYS_memcmp32(m_StringBuf.GetBuffer(), m_LastImageDict.GetBuffer(), m_StringBuf.GetSize())) { m_WordState = 0; StartDict(); InputData(m_StringBuf.GetBuffer(), m_StringBuf.GetSize()); Finish(); m_bSameLastDict = FALSE; if (m_pLastImageDict && m_bReleaseLastDict) { m_pLastImageDict->Release(); m_pLastImageDict = NULL; } if (!m_ObjectSize) { m_InlineImageState = 0; return; } m_pLastImageDict = (CPDF_Dictionary*)m_pObjectStack[--m_ObjectSize]; m_bReleaseLastDict = !m_pObjectState[m_ObjectSize]; m_pObjectState[m_ObjectSize] = FALSE; _PDF_ReplaceAbbr(m_pLastImageDict); m_LastImageDict.TakeOver(m_StringBuf); if (m_pLastImageDict->KeyExist(FX_BSTRC("ColorSpace"))) { CPDF_Object* pCSObj = m_pLastImageDict->GetElementValue(FX_BSTRC("ColorSpace")); if (pCSObj->GetType() == PDFOBJ_NAME) { CFX_ByteString name = pCSObj->GetString(); if (name != FX_BSTRC("DeviceRGB") && name != FX_BSTRC("DeviceGray") && name != FX_BSTRC("DeviceCMYK")) { pCSObj = FindResourceObj(FX_BSTRC("ColorSpace"), name); if (pCSObj) { if (!pCSObj->GetObjNum()) { pCSObj = pCSObj->Clone(); } m_pLastImageDict->SetAt(FX_BSTRC("ColorSpace"), pCSObj, m_pDocument); } } } } } else { m_bSameLastDict = TRUE; } m_ImageSrcBuf.Clear(); if (m_pLastCloneImageDict) { m_pLastCloneImageDict->Release(); } m_pLastCloneImageDict = (CPDF_Dictionary*)m_pLastImageDict->Clone(); if (m_pLastCloneImageDict->KeyExist(FX_BSTRC("Filter"))) { m_WordState = 10; m_InlineImageState = 0; } else { int width = m_pLastCloneImageDict->GetInteger(FX_BSTRC("Width")); int height = m_pLastCloneImageDict->GetInteger(FX_BSTRC("Height")); int OrigSize = 0; CPDF_Object* pCSObj = m_pLastCloneImageDict->GetElementValue(FX_BSTRC("ColorSpace")); if (pCSObj != NULL) { int bpc = m_pLastCloneImageDict->GetInteger(FX_BSTRC("BitsPerComponent")); int nComponents = 1; CPDF_ColorSpace* pCS = m_pDocument->LoadColorSpace(pCSObj); if (pCS == NULL) { nComponents = 3; } else { nComponents = pCS->CountComponents(); m_pDocument->GetPageData()->ReleaseColorSpace(pCSObj); } int pitch = (width * bpc * nComponents + 7) / 8; OrigSize = pitch * height; } else { OrigSize = ((width + 7) / 8) * height; } m_ImageSrcBuf.AppendBlock(NULL, OrigSize); m_WordState = 11; m_InlineImageState = 0; } }
CPDF_Stream* CPDF_StreamParser::ReadInlineStream(CPDF_Document* pDoc, CPDF_Dictionary* pDict, CPDF_Object* pCSObj, FX_BOOL bDecode) { if (m_Pos == m_Size) { return NULL; } if (PDF_CharType[m_pBuf[m_Pos]] == 'W') { m_Pos ++; } CFX_ByteString Decoder; CPDF_Dictionary* pParam = NULL; CPDF_Object* pFilter = pDict->GetElementValue(FX_BSTRC("Filter")); if (pFilter == NULL) { } else if (pFilter->GetType() == PDFOBJ_ARRAY) { Decoder = ((CPDF_Array*)pFilter)->GetString(0); CPDF_Array* pParams = pDict->GetArray(FX_BSTRC("DecodeParms")); if (pParams) { pParam = pParams->GetDict(0); } } else { Decoder = pFilter->GetString(); pParam = pDict->GetDict(FX_BSTRC("DecodeParms")); } FX_DWORD width = pDict->GetInteger(FX_BSTRC("Width")); FX_DWORD height = pDict->GetInteger(FX_BSTRC("Height")); FX_DWORD OrigSize = 0; if (pCSObj != NULL) { FX_DWORD bpc = pDict->GetInteger(FX_BSTRC("BitsPerComponent")); FX_DWORD nComponents = 1; CPDF_ColorSpace* pCS = pDoc->LoadColorSpace(pCSObj); if (pCS == NULL) { nComponents = 3; } else { nComponents = pCS->CountComponents(); pDoc->GetPageData()->ReleaseColorSpace(pCSObj); } FX_DWORD pitch = width; if (bpc && pitch > INT_MAX / bpc) { return NULL; } pitch *= bpc; if (nComponents && pitch > INT_MAX / nComponents) { return NULL; } pitch *= nComponents; if (pitch > INT_MAX - 7) { return NULL; } pitch += 7; pitch /= 8; OrigSize = pitch; } else { if (width > INT_MAX - 7) { return NULL; } OrigSize = ((width + 7) / 8); } if (height && OrigSize > INT_MAX / height) { return NULL; } OrigSize *= height; uint8_t* pData = NULL; FX_DWORD dwStreamSize; if (Decoder.IsEmpty()) { if (OrigSize > m_Size - m_Pos) { OrigSize = m_Size - m_Pos; } pData = FX_Alloc(uint8_t, OrigSize); FXSYS_memcpy(pData, m_pBuf + m_Pos, OrigSize); dwStreamSize = OrigSize; m_Pos += OrigSize; } else { FX_DWORD dwDestSize = OrigSize; dwStreamSize = PDF_DecodeInlineStream(m_pBuf + m_Pos, m_Size - m_Pos, width, height, Decoder, pParam, pData, dwDestSize); if ((int)dwStreamSize < 0) { return NULL; } if (bDecode) { m_Pos += dwStreamSize; dwStreamSize = dwDestSize; if (pFilter->GetType() == PDFOBJ_ARRAY) { ((CPDF_Array*)pFilter)->RemoveAt(0); CPDF_Array* pParams = pDict->GetArray(FX_BSTRC("DecodeParms")); if (pParams) { pParams->RemoveAt(0); } } else { pDict->RemoveAt(FX_BSTRC("Filter")); pDict->RemoveAt(FX_BSTRC("DecodeParms")); } } else { if (pData) { FX_Free(pData); } FX_DWORD dwSavePos = m_Pos; m_Pos += dwStreamSize; while (1) { FX_DWORD dwPrevPos = m_Pos; CPDF_StreamParser::SyntaxType type = ParseNextElement(); if (type == CPDF_StreamParser::EndOfData) { break; } if (type != CPDF_StreamParser::Keyword) { dwStreamSize += m_Pos - dwPrevPos; continue; } if (GetWordSize() == 2 && GetWordBuf()[0] == 'E' && GetWordBuf()[1] == 'I') { m_Pos = dwPrevPos; break; } dwStreamSize += m_Pos - dwPrevPos; } m_Pos = dwSavePos; pData = FX_Alloc(uint8_t, dwStreamSize); FXSYS_memcpy(pData, m_pBuf + m_Pos, dwStreamSize); m_Pos += dwStreamSize; } } pDict->SetAtInteger(FX_BSTRC("Length"), (int)dwStreamSize); return CPDF_Stream::Create(pData, dwStreamSize, pDict); }
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(); }
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; }
void CPDF_RenderStatus::DrawShading(CPDF_ShadingPattern* pPattern, CFX_Matrix* pMatrix, FX_RECT& clip_rect, int alpha, FX_BOOL bAlphaMode) { CPDF_Function** pFuncs = pPattern->m_pFunctions; int nFuncs = pPattern->m_nFuncs; CPDF_Dictionary* pDict = pPattern->m_pShadingObj->GetDict(); CPDF_ColorSpace* pColorSpace = pPattern->m_pCS; if (!pColorSpace) { return; } FX_ARGB background = 0; if (!pPattern->m_bShadingObj && pPattern->m_pShadingObj->GetDict()->KeyExist("Background")) { CPDF_Array* pBackColor = pPattern->m_pShadingObj->GetDict()->GetArray("Background"); if (pBackColor && pBackColor->GetCount() >= (FX_DWORD)pColorSpace->CountComponents()) { CFX_FixedBufGrow<FX_FLOAT, 16> comps(pColorSpace->CountComponents()); for (int i = 0; i < pColorSpace->CountComponents(); i++) { comps[i] = pBackColor->GetNumber(i); } FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; pColorSpace->GetRGB(comps, R, G, B); background = ArgbEncode(255, (int32_t)(R * 255), (int32_t)(G * 255), (int32_t)(B * 255)); } } if (pDict->KeyExist("BBox")) { CFX_FloatRect rect = pDict->GetRect("BBox"); rect.Transform(pMatrix); clip_rect.Intersect(rect.GetOutterRect()); } CPDF_DeviceBuffer buffer; buffer.Initialize(m_pContext, m_pDevice, &clip_rect, m_pCurObj, 150); CFX_Matrix FinalMatrix = *pMatrix; FinalMatrix.Concat(*buffer.GetMatrix()); CFX_DIBitmap* pBitmap = buffer.GetBitmap(); if (!pBitmap->GetBuffer()) { return; } pBitmap->Clear(background); int fill_mode = m_Options.m_Flags; switch (pPattern->m_ShadingType) { case kInvalidShading: case kMaxShading: return; case kFunctionBasedShading: DrawFuncShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs, pColorSpace, alpha); break; case kAxialShading: DrawAxialShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs, pColorSpace, alpha); break; case kRadialShading: DrawRadialShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs, pColorSpace, alpha); break; case kFreeFormGouraudTriangleMeshShading: { DrawFreeGouraudShading(pBitmap, &FinalMatrix, ToStream(pPattern->m_pShadingObj), pFuncs, nFuncs, pColorSpace, alpha); } break; case kLatticeFormGouraudTriangleMeshShading: { DrawLatticeGouraudShading(pBitmap, &FinalMatrix, ToStream(pPattern->m_pShadingObj), pFuncs, nFuncs, pColorSpace, alpha); } break; case kCoonsPatchMeshShading: case kTensorProductPatchMeshShading: { DrawCoonPatchMeshes( pPattern->m_ShadingType == kTensorProductPatchMeshShading, pBitmap, &FinalMatrix, ToStream(pPattern->m_pShadingObj), pFuncs, nFuncs, pColorSpace, fill_mode, alpha); } break; } if (bAlphaMode) { pBitmap->LoadChannel(FXDIB_Red, pBitmap, FXDIB_Alpha); } if (m_Options.m_ColorMode == RENDER_COLOR_GRAY) { pBitmap->ConvertColorScale(m_Options.m_ForeColor, m_Options.m_BackColor); } buffer.OutputToDevice(); }
CPDF_ColorSpace* CPDF_ColorSpace::Load(CPDF_Document* pDoc, CPDF_Object* pObj) { if (pObj == NULL) { return NULL; } if (pObj->GetType() == PDFOBJ_NAME) { return _CSFromName(pObj->GetString()); } if (pObj->GetType() == PDFOBJ_STREAM) { CPDF_Dictionary *pDict = ((CPDF_Stream *)pObj)->GetDict(); if (!pDict) { return NULL; } CPDF_ColorSpace *pRet = NULL; FX_POSITION pos = pDict->GetStartPos(); while (pos) { CFX_ByteString bsKey; CPDF_Object *pValue = pDict->GetNextElement(pos, bsKey); if (pValue && pValue->GetType() == PDFOBJ_NAME) { pRet = _CSFromName(pValue->GetString()); } if (pRet) { return pRet; } } return NULL; } if (pObj->GetType() != PDFOBJ_ARRAY) { return NULL; } CPDF_Array* pArray = (CPDF_Array*)pObj; if (pArray->GetCount() == 0) { return NULL; } CPDF_Object *pFamilyObj = pArray->GetElementValue(0); if (!pFamilyObj) { return NULL; } CFX_ByteString familyname = pFamilyObj->GetString(); if (pArray->GetCount() == 1) { return _CSFromName(familyname); } CPDF_ColorSpace* pCS = NULL; FX_DWORD id = familyname.GetID(); if (id == FXBSTR_ID('C', 'a', 'l', 'G')) { pCS = new CPDF_CalGray(pDoc); } else if (id == FXBSTR_ID('C', 'a', 'l', 'R')) { pCS = new CPDF_CalRGB(pDoc); } else if (id == FXBSTR_ID('L', 'a', 'b', 0)) { pCS = new CPDF_LabCS(pDoc); } else if (id == FXBSTR_ID('I', 'C', 'C', 'B')) { pCS = new CPDF_ICCBasedCS(pDoc); } else if (id == FXBSTR_ID('I', 'n', 'd', 'e') || id == FXBSTR_ID('I', 0, 0, 0)) { pCS = new CPDF_IndexedCS(pDoc); } else if (id == FXBSTR_ID('S', 'e', 'p', 'a')) { pCS = new CPDF_SeparationCS(pDoc); } else if (id == FXBSTR_ID('D', 'e', 'v', 'i')) { pCS = new CPDF_DeviceNCS(pDoc); } else if (id == FXBSTR_ID('P', 'a', 't', 't')) { pCS = new CPDF_PatternCS(pDoc); } else { return NULL; } pCS->m_pArray = pArray; if (!pCS->v_Load(pDoc, pArray)) { pCS->ReleaseCS(); return NULL; } return pCS; }
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(); }
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; }
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; }
CPDF_ShadingPattern::~CPDF_ShadingPattern() { CPDF_ColorSpace* pCS = m_pCountedCS ? m_pCountedCS->get() : nullptr; if (pCS && m_pDocument) m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray()); }
FX_BOOL CPDF_ICCBasedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { CPDF_Stream* pStream = pArray->GetStream(1); if (pStream == NULL) { return FALSE; } m_pProfile = pDoc->LoadIccProfile(pStream); if (!m_pProfile) { return FALSE; } m_nComponents = m_pProfile->GetComponents(); //Try using the nComponents from ICC profile CPDF_Dictionary* pDict = pStream->GetDict(); if (m_pProfile->m_pTransform == NULL) { // No valid ICC profile or using sRGB CPDF_Object* pAlterCSObj = pDict ? pDict->GetElementValue(FX_BSTRC("Alternate")) : NULL; if (pAlterCSObj) { CPDF_ColorSpace* pAlterCS = CPDF_ColorSpace::Load(pDoc, pAlterCSObj); if (pAlterCS) { if (m_nComponents == 0) { // NO valid ICC profile if (pAlterCS->CountComponents() > 0) { // Use Alternative colorspace m_nComponents = pAlterCS->CountComponents(); m_pAlterCS = pAlterCS; m_bOwn = TRUE; } else { // No valid alternative colorspace pAlterCS->ReleaseCS(); int32_t nDictComponents = pDict ? pDict->GetInteger(FX_BSTRC("N")) : 0; if (nDictComponents != 1 && nDictComponents != 3 && nDictComponents != 4) { return FALSE; } m_nComponents = nDictComponents; } } else { // Using sRGB if (pAlterCS->CountComponents() != m_nComponents) { pAlterCS->ReleaseCS(); } else { m_pAlterCS = pAlterCS; m_bOwn = TRUE; } } } } if (!m_pAlterCS) { if (m_nComponents == 1) { m_pAlterCS = GetStockCS(PDFCS_DEVICEGRAY); } else if (m_nComponents == 3) { m_pAlterCS = GetStockCS(PDFCS_DEVICERGB); } else if (m_nComponents == 4) { m_pAlterCS = GetStockCS(PDFCS_DEVICECMYK); } } } CPDF_Array* pRanges = pDict->GetArray(FX_BSTRC("Range")); m_pRanges = FX_Alloc2D(FX_FLOAT, m_nComponents, 2); for (int i = 0; i < m_nComponents * 2; i ++) { if (pRanges) { m_pRanges[i] = pRanges->GetNumber(i); } else if (i % 2) { m_pRanges[i] = 1.0f; } else { m_pRanges[i] = 0; } } return TRUE; }