bool CPDF_ImageRenderer::DrawMaskedImage() { if (NotDrawing()) { m_Result = false; return false; } FX_RECT rect = GetDrawRect(); if (rect.IsEmpty()) return false; CFX_Matrix new_matrix = GetDrawMatrix(rect); CFX_FxgeDevice bitmap_device1; if (!bitmap_device1.Create(rect.Width(), rect.Height(), FXDIB_Rgb32, nullptr)) return true; #if defined _SKIA_SUPPORT_ bitmap_device1.Clear(0xffffff); #else bitmap_device1.GetBitmap()->Clear(0xffffff); #endif CPDF_RenderStatus bitmap_render; bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device1, nullptr, nullptr, nullptr, nullptr, nullptr, 0, m_pRenderStatus->m_bDropObjects, nullptr, true); CPDF_ImageRenderer image_render; if (image_render.Start(&bitmap_render, m_pDIBSource, 0, 255, &new_matrix, m_Flags, true, FXDIB_BLEND_NORMAL)) { image_render.Continue(nullptr); } CFX_FxgeDevice bitmap_device2; if (!bitmap_device2.Create(rect.Width(), rect.Height(), FXDIB_8bppRgb, nullptr)) return true; #if defined _SKIA_SUPPORT_ bitmap_device2.Clear(0); #else bitmap_device2.GetBitmap()->Clear(0); #endif CalculateDrawImage(&bitmap_device1, &bitmap_device2, m_Loader.m_pMask, &new_matrix, rect); #ifdef _SKIA_SUPPORT_ m_pRenderStatus->m_pDevice->SetBitsWithMask( bitmap_device1.GetBitmap(), bitmap_device2.GetBitmap(), rect.left, rect.top, m_BitmapAlpha, m_BlendType); #else bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); if (m_BitmapAlpha < 255) bitmap_device1.GetBitmap()->MultiplyAlpha(m_BitmapAlpha); m_pRenderStatus->m_pDevice->SetDIBitsWithBlend( bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); #endif // _SKIA_SUPPORT_ return false; }
FX_BOOL CFX_GEFont::GetCharBBox(FX_WCHAR wUnicode, CFX_Rect& bbox, FX_BOOL bRecursive, FX_BOOL bCharCode) { FXSYS_assert(m_pRectArray != NULL); FXSYS_assert(m_pBBoxMap != NULL); void* pRect = NULL; if (!m_pBBoxMap->Lookup((void*)(uintptr_t)wUnicode, pRect)) { IFX_Font* pFont = NULL; int32_t iGlyph = GetGlyphIndex(wUnicode, TRUE, &pFont, bCharCode); if (iGlyph != 0xFFFF && pFont != NULL) { if (pFont == (IFX_Font*)this) { FX_RECT rtBBox; if (m_pFont->GetGlyphBBox(iGlyph, rtBBox)) { Lock(); CFX_Rect rt; rt.Set(rtBBox.left, rtBBox.top, rtBBox.Width(), rtBBox.Height()); int32_t index = m_pRectArray->Add(rt); pRect = m_pRectArray->GetPtrAt(index); m_pBBoxMap->SetAt((void*)(uintptr_t)wUnicode, pRect); Unlock(); } } else if (((CFX_GEFont*)pFont) ->GetCharBBox(wUnicode, bbox, FALSE, bCharCode)) { return TRUE; } } } if (pRect == NULL) { return FALSE; } bbox = *(FX_LPCRECT)pRect; return TRUE; }
FX_BOOL CFGAS_GEFont::GetCharBBoxInternal(FX_WCHAR wUnicode, CFX_Rect& bbox, FX_BOOL bRecursive, FX_BOOL bCharCode) { ASSERT(m_pRectArray); ASSERT(m_pBBoxMap); void* pRect = nullptr; if (!m_pBBoxMap->Lookup((void*)(uintptr_t)wUnicode, pRect)) { CFGAS_GEFont* pFont = nullptr; int32_t iGlyph = GetGlyphIndex(wUnicode, TRUE, &pFont, bCharCode); if (iGlyph != 0xFFFF && pFont) { if (pFont == this) { FX_RECT rtBBox; if (m_pFont->GetGlyphBBox(iGlyph, rtBBox)) { CFX_Rect rt; rt.Set(rtBBox.left, rtBBox.top, rtBBox.Width(), rtBBox.Height()); int32_t index = m_pRectArray->Add(rt); pRect = m_pRectArray->GetPtrAt(index); m_pBBoxMap->SetAt((void*)(uintptr_t)wUnicode, pRect); } } else if (pFont->GetCharBBoxInternal(wUnicode, bbox, FALSE, bCharCode)) { return TRUE; } } } if (!pRect) return FALSE; bbox = *static_cast<const CFX_Rect*>(pRect); return TRUE; }
bool CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device) { if (NotDrawing()) { m_Result = false; return false; } FX_RECT rect = GetDrawRect(); if (rect.IsEmpty()) return false; CFX_Matrix new_matrix = GetDrawMatrix(rect); CFX_FxgeDevice bitmap_device1; if (!bitmap_device1.Create(rect.Width(), rect.Height(), FXDIB_Rgb32, nullptr)) return true; bitmap_device1.GetBitmap()->Clear(0xffffff); CPDF_RenderStatus bitmap_render; bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device1, nullptr, nullptr, nullptr, nullptr, &m_pRenderStatus->m_Options, 0, m_pRenderStatus->m_bDropObjects, nullptr, true); CFX_Matrix patternDevice = *pObj2Device; patternDevice.Translate((FX_FLOAT)-rect.left, (FX_FLOAT)-rect.top); if (CPDF_TilingPattern* pTilingPattern = m_pPattern->AsTilingPattern()) { bitmap_render.DrawTilingPattern(pTilingPattern, m_pImageObject, &patternDevice, false); } else if (CPDF_ShadingPattern* pShadingPattern = m_pPattern->AsShadingPattern()) { bitmap_render.DrawShadingPattern(pShadingPattern, m_pImageObject, &patternDevice, false); } CFX_FxgeDevice bitmap_device2; if (!bitmap_device2.Create(rect.Width(), rect.Height(), FXDIB_8bppRgb, nullptr)) { return true; } bitmap_device2.GetBitmap()->Clear(0); CalculateDrawImage(&bitmap_device1, &bitmap_device2, m_pDIBSource, &new_matrix, rect); bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); bitmap_device1.GetBitmap()->MultiplyAlpha(255); m_pRenderStatus->m_pDevice->SetDIBitsWithBlend( bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); return false; }
FX_BOOL CPDF_RenderStatus::GetObjectClippedRect(const CPDF_PageObject* pObj, const CFX_Matrix* pObj2Device, FX_BOOL bLogical, FX_RECT& rect) const { rect = pObj->GetBBox(pObj2Device); FX_RECT rtClip = m_pDevice->GetClipBox(); if (!bLogical) { CFX_Matrix dCTM = m_pDevice->GetCTM(); FX_FLOAT a = FXSYS_fabs(dCTM.a); FX_FLOAT d = FXSYS_fabs(dCTM.d); if (a != 1.0f || d != 1.0f) { rect.right = rect.left + (int32_t)FXSYS_ceil((FX_FLOAT)rect.Width() * a); rect.bottom = rect.top + (int32_t)FXSYS_ceil((FX_FLOAT)rect.Height() * d); rtClip.right = rtClip.left + (int32_t)FXSYS_ceil((FX_FLOAT)rtClip.Width() * a); rtClip.bottom = rtClip.top + (int32_t)FXSYS_ceil((FX_FLOAT)rtClip.Height() * d); } } rect.Intersect(rtClip); return rect.IsEmpty(); }
STDMETHODIMP CDwGdiTextRenderer::DrawGlyphRun( const FX_RECT& text_bbox, __in_opt CFX_ClipRgn* pClipRgn, __in_opt DWRITE_MATRIX const* pMatrix, FLOAT baselineOriginX, FLOAT baselineOriginY, DWRITE_MEASURING_MODE measuringMode, __in DWRITE_GLYPH_RUN const* glyphRun, const COLORREF& textColor) { HRESULT hr = S_OK; if (pMatrix) { hr = pRenderTarget_->SetCurrentTransform(pMatrix); if (FAILED(hr)) { return hr; } } HDC hDC = pRenderTarget_->GetMemoryDC(); HBITMAP hBitmap = (HBITMAP)::GetCurrentObject(hDC, OBJ_BITMAP); BITMAP bitmap; GetObject(hBitmap, sizeof bitmap, &bitmap); CFX_DIBitmap dib; dib.Create(bitmap.bmWidth, bitmap.bmHeight, bitmap.bmBitsPixel == 24 ? FXDIB_Rgb : FXDIB_Rgb32, (uint8_t*)bitmap.bmBits); dib.CompositeBitmap(text_bbox.left, text_bbox.top, text_bbox.Width(), text_bbox.Height(), pBitmap_, text_bbox.left, text_bbox.top, FXDIB_BLEND_NORMAL, nullptr); hr = pRenderTarget_->DrawGlyphRun(baselineOriginX, baselineOriginY, measuringMode, glyphRun, pRenderingParams_, textColor); if (FAILED(hr)) { return hr; } pBitmap_->CompositeBitmap(text_bbox.left, text_bbox.top, text_bbox.Width(), text_bbox.Height(), &dib, text_bbox.left, text_bbox.top, FXDIB_BLEND_NORMAL, pClipRgn); return hr; }
FX_FLOAT CPWL_Edit::GetCharArrayAutoFontSize(CPDF_Font* pFont, const CPDF_Rect& rcPlate, int32_t nCharArray) { if (pFont && !pFont->IsStandardFont()) { FX_RECT rcBBox; pFont->GetFontBBox(rcBBox); CPDF_Rect rcCell = rcPlate; FX_FLOAT xdiv = rcCell.Width() / nCharArray * 1000.0f / rcBBox.Width(); FX_FLOAT ydiv = -rcCell.Height() * 1000.0f / rcBBox.Height(); return xdiv < ydiv ? xdiv : ydiv; } return 0.0f; }
FX_FLOAT CPDF_TextObject::GetSpaceCharWidth() const { CPDF_Font* pFont = m_TextState.GetFont(); FX_DWORD charCode = m_TextState.GetFont()->CharCodeFromUnicode(32); if (charCode != (FX_DWORD)-1) { return GetCharWidth(charCode); } FX_FLOAT fontSize = m_TextState.GetFontSize() / 4000.0f; FX_BOOL bVertWriting = FALSE; CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); if (pCIDFont) { bVertWriting = pCIDFont->IsVertWriting(); } FX_RECT fontRect; pFont->GetFontBBox(fontRect); fontSize *= bVertWriting ? (FX_FLOAT)fontRect.Height() : (FX_FLOAT)fontRect.Width(); return fontSize; }
CFX_DIBitmap* CPDF_RenderStatus::GetBackdrop(const CPDF_PageObject* pObj, const FX_RECT& rect, int& left, int& top, FX_BOOL bBackAlphaRequired) { FX_RECT bbox = rect; bbox.Intersect(m_pDevice->GetClipBox()); left = bbox.left; top = bbox.top; CFX_Matrix deviceCTM = m_pDevice->GetCTM(); FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a); FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d); int width = FXSYS_round(bbox.Width() * scaleX); int height = FXSYS_round(bbox.Height() * scaleY); std::unique_ptr<CFX_DIBitmap> pBackdrop(new CFX_DIBitmap); if (bBackAlphaRequired && !m_bDropObjects) pBackdrop->Create(width, height, FXDIB_Argb); else m_pDevice->CreateCompatibleBitmap(pBackdrop.get(), width, height); if (!pBackdrop->GetBuffer()) return nullptr; FX_BOOL bNeedDraw; if (pBackdrop->HasAlpha()) bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT); else bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS); if (!bNeedDraw) { m_pDevice->GetDIBits(pBackdrop.get(), left, top); return pBackdrop.release(); } CFX_Matrix FinalMatrix = m_DeviceMatrix; FinalMatrix.TranslateI(-left, -top); FinalMatrix.Scale(scaleX, scaleY); pBackdrop->Clear(pBackdrop->HasAlpha() ? 0 : 0xffffffff); CFX_FxgeDevice device; device.Attach(pBackdrop.get(), false, nullptr, false); m_pContext->Render(&device, pObj, &m_Options, &FinalMatrix); return pBackdrop.release(); }
void CPDF_ImageRenderer::CalculateDrawImage(CFX_FxgeDevice* pBitmapDevice1, CFX_FxgeDevice* pBitmapDevice2, const CFX_DIBSource* pDIBSource, CFX_Matrix* pNewMatrix, const FX_RECT& rect) const { CPDF_RenderStatus bitmap_render; bitmap_render.Initialize(m_pRenderStatus->m_pContext, pBitmapDevice2, nullptr, nullptr, nullptr, nullptr, nullptr, 0, m_pRenderStatus->m_bDropObjects, nullptr, true); CPDF_ImageRenderer image_render; if (image_render.Start(&bitmap_render, pDIBSource, 0xffffffff, 255, pNewMatrix, m_Flags, true, FXDIB_BLEND_NORMAL)) { image_render.Continue(nullptr); } if (m_Loader.m_MatteColor == 0xffffffff) return; int matte_r = FXARGB_R(m_Loader.m_MatteColor); int matte_g = FXARGB_G(m_Loader.m_MatteColor); int matte_b = FXARGB_B(m_Loader.m_MatteColor); for (int row = 0; row < rect.Height(); row++) { uint8_t* dest_scan = const_cast<uint8_t*>(pBitmapDevice1->GetBitmap()->GetScanline(row)); const uint8_t* mask_scan = pBitmapDevice2->GetBitmap()->GetScanline(row); for (int col = 0; col < rect.Width(); col++) { int alpha = *mask_scan++; if (!alpha) { dest_scan += 4; continue; } int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; *dest_scan++ = std::min(std::max(orig, 0), 255); orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; *dest_scan++ = std::min(std::max(orig, 0), 255); orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; *dest_scan++ = std::min(std::max(orig, 0), 255); dest_scan++; } } }
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; }
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; }
FX_BOOL CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device) { if (m_pRenderStatus->m_bPrint && !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { m_Result = FALSE; return FALSE; } FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOutterRect(); rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox()); if (rect.IsEmpty()) { return FALSE; } CFX_AffineMatrix new_matrix = m_ImageMatrix; new_matrix.TranslateI(-rect.left, -rect.top); int width = rect.Width(); int height = rect.Height(); CFX_FxgeDevice bitmap_device1; if (!bitmap_device1.Create(rect.Width(), rect.Height(), FXDIB_Rgb32)) { return TRUE; } bitmap_device1.GetBitmap()->Clear(0xffffff); { CPDF_RenderStatus bitmap_render; bitmap_render.Initialize(m_pRenderStatus->m_Level + 1, m_pRenderStatus->m_pContext, &bitmap_device1, NULL, NULL, NULL, NULL, &m_pRenderStatus->m_Options, 0, m_pRenderStatus->m_bDropObjects, NULL, TRUE); CFX_Matrix patternDevice = *pObj2Device; patternDevice.Translate((FX_FLOAT) - rect.left, (FX_FLOAT) - rect.top); if(m_pPattern->m_PatternType == PATTERN_TILING) { bitmap_render.DrawTilingPattern((CPDF_TilingPattern*)m_pPattern, m_pImageObject, &patternDevice, FALSE); } else { bitmap_render.DrawShadingPattern((CPDF_ShadingPattern*)m_pPattern, m_pImageObject, &patternDevice, FALSE); } } { CFX_FxgeDevice bitmap_device2; if (!bitmap_device2.Create(rect.Width(), rect.Height(), FXDIB_8bppRgb)) { return TRUE; } bitmap_device2.GetBitmap()->Clear(0); CPDF_RenderStatus bitmap_render; bitmap_render.Initialize(m_pRenderStatus->m_Level + 1, m_pRenderStatus->m_pContext, &bitmap_device2, NULL, NULL, NULL, NULL, NULL, 0, m_pRenderStatus->m_bDropObjects, NULL, TRUE); CPDF_ImageRenderer image_render; if (image_render.Start(&bitmap_render, m_pDIBSource, 0xffffffff, 255, &new_matrix, m_Flags, TRUE)) { image_render.Continue(NULL); } if (m_Loader.m_MatteColor != 0xffffffff) { int matte_r = FXARGB_R(m_Loader.m_MatteColor); int matte_g = FXARGB_G(m_Loader.m_MatteColor); int matte_b = FXARGB_B(m_Loader.m_MatteColor); for (int row = 0; row < height; row ++) { FX_LPBYTE dest_scan = (FX_LPBYTE)bitmap_device1.GetBitmap()->GetScanline(row); FX_LPCBYTE mask_scan = bitmap_device2.GetBitmap()->GetScanline(row); for (int col = 0; col < width; col ++) { int alpha = *mask_scan ++; if (alpha) { int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; if (orig < 0) { orig = 0; } else if (orig > 255) { orig = 255; } *dest_scan++ = orig; orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; if (orig < 0) { orig = 0; } else if (orig > 255) { orig = 255; } *dest_scan++ = orig; orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; if (orig < 0) { orig = 0; } else if (orig > 255) { orig = 255; } *dest_scan++ = orig; dest_scan ++; } else { dest_scan += 4; } } } } bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); bitmap_device1.GetBitmap()->MultiplyAlpha(255); } m_pRenderStatus->m_pDevice->SetDIBits(bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); return FALSE; }
FX_BOOL CPDF_RenderStatus::ProcessType3Text(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device) { CPDF_Type3Font* pType3Font = textobj->m_TextState.GetFont()->GetType3Font(); for (int j = 0; j < m_Type3FontCache.GetSize(); j++) if ((CPDF_Type3Font*)m_Type3FontCache.GetAt(j) == pType3Font) { return TRUE; } CFX_Matrix dCTM = m_pDevice->GetCTM(); FX_FLOAT sa = FXSYS_fabs(dCTM.a); FX_FLOAT sd = FXSYS_fabs(dCTM.d); CFX_AffineMatrix text_matrix; textobj->GetTextMatrix(&text_matrix); CFX_AffineMatrix char_matrix = pType3Font->GetFontMatrix(); FX_FLOAT font_size = textobj->m_TextState.GetFontSize(); char_matrix.Scale(font_size, font_size); FX_ARGB fill_argb = GetFillArgb(textobj, TRUE); int fill_alpha = FXARGB_A(fill_argb); int device_class = m_pDevice->GetDeviceClass(); FXTEXT_GLYPHPOS* pGlyphAndPos = NULL; if (device_class == FXDC_DISPLAY) { pGlyphAndPos = FX_Alloc(FXTEXT_GLYPHPOS, textobj->m_nChars); } else if (fill_alpha < 255) { return FALSE; } CPDF_RefType3Cache refTypeCache(pType3Font); FX_DWORD *pChars = textobj->m_pCharCodes; if (textobj->m_nChars == 1) { pChars = (FX_DWORD*)(&textobj->m_pCharCodes); } for (int iChar = 0; iChar < textobj->m_nChars; iChar ++) { FX_DWORD charcode = pChars[iChar]; if (charcode == (FX_DWORD) - 1) { continue; } CPDF_Type3Char* pType3Char = pType3Font->LoadChar(charcode); if (pType3Char == NULL) { continue; } CFX_AffineMatrix matrix = char_matrix; matrix.e += iChar ? textobj->m_pCharPos[iChar - 1] : 0; matrix.Concat(text_matrix); matrix.Concat(*pObj2Device); if (!pType3Char->LoadBitmap(m_pContext)) { if (pGlyphAndPos) { for (int i = 0; i < iChar; i ++) { FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[i]; if (glyph.m_pGlyph == NULL) { continue; } m_pDevice->SetBitMask(&glyph.m_pGlyph->m_Bitmap, glyph.m_OriginX + glyph.m_pGlyph->m_Left, glyph.m_OriginY - glyph.m_pGlyph->m_Top, fill_argb); } FX_Free(pGlyphAndPos); pGlyphAndPos = NULL; } CPDF_GraphicStates* pStates = CloneObjStates(textobj, FALSE); CPDF_RenderOptions Options = m_Options; Options.m_Flags |= RENDER_FORCE_HALFTONE | RENDER_RECT_AA; Options.m_Flags &= ~RENDER_FORCE_DOWNSAMPLE; CPDF_Dictionary* pFormResource = NULL; if (pType3Char->m_pForm && pType3Char->m_pForm->m_pFormDict) { pFormResource = pType3Char->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources")); } if (fill_alpha == 255) { CPDF_RenderStatus status; status.Initialize(m_Level + 1, m_pContext, m_pDevice, NULL, NULL, this, pStates, &Options, pType3Char->m_pForm->m_Transparency, m_bDropObjects, pFormResource, FALSE, pType3Char, fill_argb); status.m_Type3FontCache.Append(m_Type3FontCache); status.m_Type3FontCache.Add(pType3Font); m_pDevice->SaveState(); status.RenderObjectList(pType3Char->m_pForm, &matrix); m_pDevice->RestoreState(); } else { CFX_FloatRect rect_f = pType3Char->m_pForm->CalcBoundingBox(); rect_f.Transform(&matrix); FX_RECT rect = rect_f.GetOutterRect(); CFX_FxgeDevice bitmap_device; if (!bitmap_device.Create((int)(rect.Width() * sa), (int)(rect.Height() * sd), FXDIB_Argb)) { return TRUE; } bitmap_device.GetBitmap()->Clear(0); CPDF_RenderStatus status; status.Initialize(m_Level + 1, m_pContext, &bitmap_device, NULL, NULL, this, pStates, &Options, pType3Char->m_pForm->m_Transparency, m_bDropObjects, pFormResource, FALSE, pType3Char, fill_argb); status.m_Type3FontCache.Append(m_Type3FontCache); status.m_Type3FontCache.Add(pType3Font); matrix.TranslateI(-rect.left, -rect.top); matrix.Scale(sa, sd); status.RenderObjectList(pType3Char->m_pForm, &matrix); m_pDevice->SetDIBits(bitmap_device.GetBitmap(), rect.left, rect.top); } delete pStates; } else if (pType3Char->m_pBitmap) { if (device_class == FXDC_DISPLAY) { CPDF_Type3Cache* pCache = GetCachedType3(pType3Font); refTypeCache.m_dwCount++; CFX_GlyphBitmap* pBitmap = pCache->LoadGlyph(charcode, &matrix, sa, sd); if (pBitmap == NULL) { continue; } int origin_x = FXSYS_round(matrix.e); int origin_y = FXSYS_round(matrix.f); if (pGlyphAndPos) { pGlyphAndPos[iChar].m_pGlyph = pBitmap; pGlyphAndPos[iChar].m_OriginX = origin_x; pGlyphAndPos[iChar].m_OriginY = origin_y; } else { m_pDevice->SetBitMask(&pBitmap->m_Bitmap, origin_x + pBitmap->m_Left, origin_y - pBitmap->m_Top, fill_argb); } } else { CFX_AffineMatrix image_matrix = pType3Char->m_ImageMatrix; image_matrix.Concat(matrix); CPDF_ImageRenderer renderer; if (renderer.Start(this, pType3Char->m_pBitmap, fill_argb, 255, &image_matrix, 0, FALSE)) { renderer.Continue(NULL); } if (!renderer.m_Result) { return FALSE; } } } } if (pGlyphAndPos) { FX_RECT rect = FXGE_GetGlyphsBBox(pGlyphAndPos, textobj->m_nChars, 0, sa, sd); CFX_DIBitmap bitmap; if (!bitmap.Create((int)(rect.Width() * sa), (int)(rect.Height() * sd), FXDIB_8bppMask)) { FX_Free(pGlyphAndPos); return TRUE; } bitmap.Clear(0); for (int iChar = 0; iChar < textobj->m_nChars; iChar ++) { FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar]; if (glyph.m_pGlyph == NULL) { continue; } bitmap.TransferBitmap((int)((glyph.m_OriginX + glyph.m_pGlyph->m_Left - rect.left) * sa), (int)((glyph.m_OriginY - glyph.m_pGlyph->m_Top - rect.top) * sd), glyph.m_pGlyph->m_Bitmap.GetWidth(), glyph.m_pGlyph->m_Bitmap.GetHeight(), &glyph.m_pGlyph->m_Bitmap, 0, 0); } m_pDevice->SetBitMask(&bitmap, rect.left, rect.top, fill_argb); FX_Free(pGlyphAndPos); } return TRUE; }
CStretchEngine::CStretchEngine(IFX_ScanlineComposer* pDestBitmap, FXDIB_Format dest_format, int dest_width, int dest_height, const FX_RECT& clip_rect, const CFX_DIBSource* pSrcBitmap, int flags) { m_State = 0; m_DestFormat = dest_format; m_DestBpp = dest_format & 0xff; m_SrcBpp = pSrcBitmap->GetFormat() & 0xff; m_bHasAlpha = pSrcBitmap->GetFormat() & 0x200; m_pSrcPalette = pSrcBitmap->GetPalette(); m_pDestBitmap = pDestBitmap; m_DestWidth = dest_width; m_DestHeight = dest_height; m_pInterBuf = NULL; m_pExtraAlphaBuf = NULL; m_pDestMaskScanline = NULL; m_DestClip = clip_rect; FX_DWORD size = clip_rect.Width(); if (size && m_DestBpp > (int)(INT_MAX / size)) { return; } size *= m_DestBpp; if (size > INT_MAX - 31) { return; } size += 31; size = size / 32 * 4; m_pDestScanline = FX_AllocNL(FX_BYTE, size); if (m_pDestScanline == NULL) { return; } if (dest_format == FXDIB_Rgb32) { FXSYS_memset8(m_pDestScanline, 255, size); } m_InterPitch = (m_DestClip.Width() * m_DestBpp + 31) / 32 * 4; m_ExtraMaskPitch = (m_DestClip.Width() * 8 + 31) / 32 * 4; m_pInterBuf = NULL; m_pSource = pSrcBitmap; m_SrcWidth = pSrcBitmap->GetWidth(); m_SrcHeight = pSrcBitmap->GetHeight(); m_SrcPitch = (m_SrcWidth * m_SrcBpp + 31) / 32 * 4; if ((flags & FXDIB_NOSMOOTH) == 0) { FX_BOOL bInterpol = flags & FXDIB_INTERPOL || flags & FXDIB_BICUBIC_INTERPOL; if (!bInterpol && FXSYS_abs(dest_width) != 0 && FXSYS_abs(dest_height) < m_SrcWidth * m_SrcHeight * 8 / FXSYS_abs(dest_width)) { flags = FXDIB_INTERPOL; } m_Flags = flags; } else { m_Flags = FXDIB_NOSMOOTH; if (flags & FXDIB_DOWNSAMPLE) { m_Flags |= FXDIB_DOWNSAMPLE; } } double scale_x = FXSYS_Div((FX_FLOAT)(m_SrcWidth), (FX_FLOAT)(m_DestWidth)); double scale_y = FXSYS_Div((FX_FLOAT)(m_SrcHeight), (FX_FLOAT)(m_DestHeight)); double base_x = m_DestWidth > 0 ? 0.0f : (FX_FLOAT)(m_DestWidth); double base_y = m_DestHeight > 0 ? 0.0f : (FX_FLOAT)(m_DestHeight); double src_left = FXSYS_Mul(scale_x, (FX_FLOAT)(clip_rect.left) + base_x); double src_right = FXSYS_Mul(scale_x, (FX_FLOAT)(clip_rect.right) + base_x); double src_top = FXSYS_Mul(scale_y, (FX_FLOAT)(clip_rect.top) + base_y); double src_bottom = FXSYS_Mul(scale_y, (FX_FLOAT)(clip_rect.bottom) + base_y); if (src_left > src_right) { double temp = src_left; src_left = src_right; src_right = temp; } if (src_top > src_bottom) { double temp = src_top; src_top = src_bottom; src_bottom = temp; } m_SrcClip.left = (int)FXSYS_floor((FX_FLOAT)src_left); m_SrcClip.right = (int)FXSYS_ceil((FX_FLOAT)src_right); m_SrcClip.top = (int)FXSYS_floor((FX_FLOAT)src_top); m_SrcClip.bottom = (int)FXSYS_ceil((FX_FLOAT)src_bottom); FX_RECT src_rect(0, 0, m_SrcWidth, m_SrcHeight); m_SrcClip.Intersect(src_rect); if (m_SrcBpp == 1) { if (m_DestBpp == 8) { m_TransMethod = 1; } else { m_TransMethod = 2; } } else if (m_SrcBpp == 8) { if (m_DestBpp == 8) { if (!m_bHasAlpha) { m_TransMethod = 3; } else { m_TransMethod = 4; } } else { if (!m_bHasAlpha) { m_TransMethod = 5; } else { m_TransMethod = 6; } } } else { if (!m_bHasAlpha) { m_TransMethod = 7; } else { m_TransMethod = 8; } } }
FX_BOOL CPDF_ImageRenderer::DrawMaskedImage() { if (m_pRenderStatus->m_bPrint && !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { m_Result = FALSE; return FALSE; } FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOutterRect(); rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox()); if (rect.IsEmpty()) { return FALSE; } CFX_AffineMatrix new_matrix = m_ImageMatrix; new_matrix.TranslateI(-rect.left, -rect.top); int width = rect.Width(); int height = rect.Height(); CFX_FxgeDevice bitmap_device1; if (!bitmap_device1.Create(width, height, FXDIB_Rgb32)) { return TRUE; } bitmap_device1.GetBitmap()->Clear(0xffffff); { CPDF_RenderStatus bitmap_render; bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device1, NULL, NULL, NULL, NULL, NULL, 0, m_pRenderStatus->m_bDropObjects, NULL, TRUE); CPDF_ImageRenderer image_render; if (image_render.Start(&bitmap_render, m_pDIBSource, 0, 255, &new_matrix, m_Flags, TRUE)) { image_render.Continue(NULL); } } { CFX_FxgeDevice bitmap_device2; if (!bitmap_device2.Create(width, height, FXDIB_8bppRgb)) { return TRUE; } bitmap_device2.GetBitmap()->Clear(0); CPDF_RenderStatus bitmap_render; bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device2, NULL, NULL, NULL, NULL, NULL, 0, m_pRenderStatus->m_bDropObjects, NULL, TRUE); CPDF_ImageRenderer image_render; if (image_render.Start(&bitmap_render, m_Loader.m_pMask, 0xffffffff, 255, &new_matrix, m_Flags, TRUE)) { image_render.Continue(NULL); } if (m_Loader.m_MatteColor != 0xffffffff) { int matte_r = FXARGB_R(m_Loader.m_MatteColor); int matte_g = FXARGB_G(m_Loader.m_MatteColor); int matte_b = FXARGB_B(m_Loader.m_MatteColor); for (int row = 0; row < height; row++) { uint8_t* dest_scan = (uint8_t*)bitmap_device1.GetBitmap()->GetScanline(row); const uint8_t* mask_scan = bitmap_device2.GetBitmap()->GetScanline(row); for (int col = 0; col < width; col++) { int alpha = *mask_scan++; if (alpha) { int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; if (orig < 0) { orig = 0; } else if (orig > 255) { orig = 255; } *dest_scan++ = orig; orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; if (orig < 0) { orig = 0; } else if (orig > 255) { orig = 255; } *dest_scan++ = orig; orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; if (orig < 0) { orig = 0; } else if (orig > 255) { orig = 255; } *dest_scan++ = orig; dest_scan++; } else { dest_scan += 4; } } } } bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); if (m_BitmapAlpha < 255) { bitmap_device1.GetBitmap()->MultiplyAlpha(m_BitmapAlpha); } } m_pRenderStatus->m_pDevice->SetDIBits(bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); return FALSE; }
bool CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device) { if (m_pRenderStatus->m_bPrint && !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { m_Result = false; return false; } FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOuterRect(); rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox()); if (rect.IsEmpty()) { return false; } CFX_Matrix new_matrix = m_ImageMatrix; new_matrix.TranslateI(-rect.left, -rect.top); int width = rect.Width(); int height = rect.Height(); CFX_FxgeDevice bitmap_device1; if (!bitmap_device1.Create(rect.Width(), rect.Height(), FXDIB_Rgb32, nullptr)) return true; bitmap_device1.GetBitmap()->Clear(0xffffff); { CPDF_RenderStatus bitmap_render; bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device1, nullptr, nullptr, nullptr, nullptr, &m_pRenderStatus->m_Options, 0, m_pRenderStatus->m_bDropObjects, nullptr, true); CFX_Matrix patternDevice = *pObj2Device; patternDevice.Translate((FX_FLOAT)-rect.left, (FX_FLOAT)-rect.top); if (CPDF_TilingPattern* pTilingPattern = m_pPattern->AsTilingPattern()) { bitmap_render.DrawTilingPattern(pTilingPattern, m_pImageObject, &patternDevice, false); } else if (CPDF_ShadingPattern* pShadingPattern = m_pPattern->AsShadingPattern()) { bitmap_render.DrawShadingPattern(pShadingPattern, m_pImageObject, &patternDevice, false); } } { CFX_FxgeDevice bitmap_device2; if (!bitmap_device2.Create(rect.Width(), rect.Height(), FXDIB_8bppRgb, nullptr)) { return true; } bitmap_device2.GetBitmap()->Clear(0); CPDF_RenderStatus bitmap_render; bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device2, nullptr, nullptr, nullptr, nullptr, nullptr, 0, m_pRenderStatus->m_bDropObjects, nullptr, true); CPDF_ImageRenderer image_render; if (image_render.Start(&bitmap_render, m_pDIBSource, 0xffffffff, 255, &new_matrix, m_Flags, true)) { image_render.Continue(nullptr); } if (m_Loader.m_MatteColor != 0xffffffff) { int matte_r = FXARGB_R(m_Loader.m_MatteColor); int matte_g = FXARGB_G(m_Loader.m_MatteColor); int matte_b = FXARGB_B(m_Loader.m_MatteColor); for (int row = 0; row < height; row++) { uint8_t* dest_scan = (uint8_t*)bitmap_device1.GetBitmap()->GetScanline(row); const uint8_t* mask_scan = bitmap_device2.GetBitmap()->GetScanline(row); for (int col = 0; col < width; col++) { int alpha = *mask_scan++; if (alpha) { int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; if (orig < 0) { orig = 0; } else if (orig > 255) { orig = 255; } *dest_scan++ = orig; orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; if (orig < 0) { orig = 0; } else if (orig > 255) { orig = 255; } *dest_scan++ = orig; orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; if (orig < 0) { orig = 0; } else if (orig > 255) { orig = 255; } *dest_scan++ = orig; dest_scan++; } else { dest_scan += 4; } } } } bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); bitmap_device1.GetBitmap()->MultiplyAlpha(255); } m_pRenderStatus->m_pDevice->SetDIBitsWithBlend( bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); return false; }