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; }
void CPDF_DeviceBuffer::OutputToDevice() { if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) { if (m_Matrix.a == 1.0f && m_Matrix.d == 1.0f) { m_pDevice->SetDIBits(m_pBitmap.get(), m_Rect.left, m_Rect.top); } else { m_pDevice->StretchDIBits(m_pBitmap.get(), m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height()); } } else { CFX_DIBitmap buffer; m_pDevice->CreateCompatibleBitmap(&buffer, m_pBitmap->GetWidth(), m_pBitmap->GetHeight()); m_pContext->GetBackground(&buffer, m_pObject, nullptr, &m_Matrix); buffer.CompositeBitmap(0, 0, buffer.GetWidth(), buffer.GetHeight(), m_pBitmap.get(), 0, 0); m_pDevice->StretchDIBits(&buffer, m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height()); } }
void CPDF_RenderStatus::DrawTilingPattern(CPDF_TilingPattern* pPattern, CPDF_PageObject* pPageObj, const CFX_Matrix* pObj2Device, FX_BOOL bStroke) { if (!pPattern->Load()) { return; } m_pDevice->SaveState(); if (pPageObj->m_Type == PDFPAGE_PATH) { if (!SelectClipPath((CPDF_PathObject*)pPageObj, pObj2Device, bStroke)) { m_pDevice->RestoreState(); return; } } else if (pPageObj->m_Type == PDFPAGE_IMAGE) { FX_RECT rect = pPageObj->GetBBox(pObj2Device); m_pDevice->SetClip_Rect(&rect); } else { return; } FX_RECT clip_box = m_pDevice->GetClipBox(); if (clip_box.IsEmpty()) { m_pDevice->RestoreState(); return; } CFX_Matrix dCTM = m_pDevice->GetCTM(); FX_FLOAT sa = FXSYS_fabs(dCTM.a); FX_FLOAT sd = FXSYS_fabs(dCTM.d); clip_box.right = clip_box.left + (int32_t)FXSYS_ceil(clip_box.Width() * sa); clip_box.bottom = clip_box.top + (int32_t)FXSYS_ceil(clip_box.Height() * sd); CFX_Matrix mtPattern2Device = pPattern->m_Pattern2Form; mtPattern2Device.Concat(*pObj2Device); GetScaledMatrix(mtPattern2Device); FX_BOOL bAligned = FALSE; if (pPattern->m_BBox.left == 0 && pPattern->m_BBox.bottom == 0 && pPattern->m_BBox.right == pPattern->m_XStep && pPattern->m_BBox.top == pPattern->m_YStep && (mtPattern2Device.IsScaled() || mtPattern2Device.Is90Rotated())) { bAligned = TRUE; } CFX_FloatRect cell_bbox = pPattern->m_BBox; mtPattern2Device.TransformRect(cell_bbox); int width = (int)FXSYS_ceil(cell_bbox.Width()); int height = (int)FXSYS_ceil(cell_bbox.Height()); if (width == 0) { width = 1; } if (height == 0) { height = 1; } int min_col, max_col, min_row, max_row; CFX_Matrix mtDevice2Pattern; mtDevice2Pattern.SetReverse(mtPattern2Device); CFX_FloatRect clip_box_p(clip_box); clip_box_p.Transform(&mtDevice2Pattern); min_col = (int)FXSYS_ceil( FXSYS_Div(clip_box_p.left - pPattern->m_BBox.right, pPattern->m_XStep)); max_col = (int)FXSYS_floor( FXSYS_Div(clip_box_p.right - pPattern->m_BBox.left, pPattern->m_XStep)); min_row = (int)FXSYS_ceil( FXSYS_Div(clip_box_p.bottom - pPattern->m_BBox.top, pPattern->m_YStep)); max_row = (int)FXSYS_floor( FXSYS_Div(clip_box_p.top - pPattern->m_BBox.bottom, pPattern->m_YStep)); if (width > clip_box.Width() || height > clip_box.Height() || width * height > clip_box.Width() * clip_box.Height()) { CPDF_GraphicStates* pStates = NULL; if (!pPattern->m_bColored) { pStates = CloneObjStates(pPageObj, bStroke); } CPDF_Dictionary* pFormResource = NULL; if (pPattern->m_pForm->m_pFormDict) { pFormResource = pPattern->m_pForm->m_pFormDict->GetDict("Resources"); } for (int col = min_col; col <= max_col; col++) for (int row = min_row; row <= max_row; row++) { FX_FLOAT orig_x, orig_y; orig_x = col * pPattern->m_XStep; orig_y = row * pPattern->m_YStep; mtPattern2Device.Transform(orig_x, orig_y); CFX_Matrix matrix = *pObj2Device; matrix.Translate(orig_x - mtPattern2Device.e, orig_y - mtPattern2Device.f); m_pDevice->SaveState(); CPDF_RenderStatus status; status.Initialize(m_pContext, m_pDevice, NULL, NULL, this, pStates, &m_Options, pPattern->m_pForm->m_Transparency, m_bDropObjects, pFormResource); status.RenderObjectList(pPattern->m_pForm, &matrix); m_pDevice->RestoreState(); } m_pDevice->RestoreState(); delete pStates; return; } if (bAligned) { int orig_x = FXSYS_round(mtPattern2Device.e); int orig_y = FXSYS_round(mtPattern2Device.f); min_col = (clip_box.left - orig_x) / width; if (clip_box.left < orig_x) { min_col--; } max_col = (clip_box.right - orig_x) / width; if (clip_box.right <= orig_x) { max_col--; } min_row = (clip_box.top - orig_y) / height; if (clip_box.top < orig_y) { min_row--; } max_row = (clip_box.bottom - orig_y) / height; if (clip_box.bottom <= orig_y) { max_row--; } } FX_FLOAT left_offset = cell_bbox.left - mtPattern2Device.e; FX_FLOAT top_offset = cell_bbox.bottom - mtPattern2Device.f; CFX_DIBitmap* pPatternBitmap = NULL; if (width * height < 16) { CFX_DIBitmap* pEnlargedBitmap = DrawPatternBitmap(m_pContext->m_pDocument, m_pContext->m_pPageCache, pPattern, pObj2Device, 8, 8, m_Options.m_Flags); pPatternBitmap = pEnlargedBitmap->StretchTo(width, height); delete pEnlargedBitmap; } else { pPatternBitmap = DrawPatternBitmap( m_pContext->m_pDocument, m_pContext->m_pPageCache, pPattern, pObj2Device, width, height, m_Options.m_Flags); } if (!pPatternBitmap) { m_pDevice->RestoreState(); return; } if (m_Options.m_ColorMode == RENDER_COLOR_GRAY) { pPatternBitmap->ConvertColorScale(m_Options.m_ForeColor, m_Options.m_BackColor); } FX_ARGB fill_argb = GetFillArgb(pPageObj); int clip_width = clip_box.right - clip_box.left; int clip_height = clip_box.bottom - clip_box.top; CFX_DIBitmap screen; if (!screen.Create(clip_width, clip_height, FXDIB_Argb)) { return; } screen.Clear(0); FX_DWORD* src_buf = (FX_DWORD*)pPatternBitmap->GetBuffer(); for (int col = min_col; col <= max_col; col++) { for (int row = min_row; row <= max_row; row++) { int start_x, start_y; if (bAligned) { start_x = FXSYS_round(mtPattern2Device.e) + col * width - clip_box.left; start_y = FXSYS_round(mtPattern2Device.f) + row * height - clip_box.top; } else { FX_FLOAT orig_x = col * pPattern->m_XStep; FX_FLOAT orig_y = row * pPattern->m_YStep; mtPattern2Device.Transform(orig_x, orig_y); start_x = FXSYS_round(orig_x + left_offset) - clip_box.left; start_y = FXSYS_round(orig_y + top_offset) - clip_box.top; } if (width == 1 && height == 1) { if (start_x < 0 || start_x >= clip_box.Width() || start_y < 0 || start_y >= clip_box.Height()) { continue; } FX_DWORD* dest_buf = (FX_DWORD*)(screen.GetBuffer() + screen.GetPitch() * start_y + start_x * 4); if (pPattern->m_bColored) { *dest_buf = *src_buf; } else { *dest_buf = (*(uint8_t*)src_buf << 24) | (fill_argb & 0xffffff); } } else { if (pPattern->m_bColored) { screen.CompositeBitmap(start_x, start_y, width, height, pPatternBitmap, 0, 0); } else { screen.CompositeMask(start_x, start_y, width, height, pPatternBitmap, fill_argb, 0, 0); } } } } CompositeDIBitmap(&screen, clip_box.left, clip_box.top, 0, 255, FXDIB_BLEND_NORMAL, FALSE); m_pDevice->RestoreState(); delete pPatternBitmap; }
void CPDF_RenderStatus::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, int left, int top, FX_ARGB mask_argb, int bitmap_alpha, int blend_mode, int Transparency) { if (pDIBitmap == NULL) { return; } FX_BOOL bIsolated = Transparency & PDFTRANS_ISOLATED; FX_BOOL bGroup = Transparency & PDFTRANS_GROUP; if (blend_mode == FXDIB_BLEND_NORMAL) { if (!pDIBitmap->IsAlphaMask()) { if (bitmap_alpha < 255) { pDIBitmap->MultiplyAlpha(bitmap_alpha); } if (m_pDevice->SetDIBits(pDIBitmap, left, top)) { return; } } else { FX_DWORD fill_argb = m_Options.TranslateColor(mask_argb); if (bitmap_alpha < 255) { ((uint8_t*)&fill_argb)[3] = ((uint8_t*)&fill_argb)[3] * bitmap_alpha / 255; } if (m_pDevice->SetBitMask(pDIBitmap, left, top, fill_argb)) { return; } } } FX_BOOL bBackAlphaRequired = blend_mode && bIsolated && !m_bDropObjects; FX_BOOL bGetBackGround = ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) || (!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) && (m_pDevice->GetRenderCaps() & FXRC_GET_BITS) && !bBackAlphaRequired); if (bGetBackGround) { if (bIsolated || !bGroup) { if (pDIBitmap->IsAlphaMask()) { return; } m_pDevice->SetDIBits(pDIBitmap, left, top, blend_mode); } else { FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), top + pDIBitmap->GetHeight()); rect.Intersect(m_pDevice->GetClipBox()); CFX_DIBitmap* pClone = NULL; FX_BOOL bClone = FALSE; if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) { bClone = TRUE; pClone = m_pDevice->GetBackDrop()->Clone(&rect); CFX_DIBitmap* pForeBitmap = m_pDevice->GetBitmap(); pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), pForeBitmap, rect.left, rect.top); left = left >= 0 ? 0 : left; top = top >= 0 ? 0 : top; if (!pDIBitmap->IsAlphaMask()) pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), pDIBitmap, left, top, blend_mode); else pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(), pDIBitmap, mask_argb, left, top, blend_mode); } else { pClone = pDIBitmap; } if (m_pDevice->GetBackDrop()) { m_pDevice->SetDIBits(pClone, rect.left, rect.top); } else { if (pDIBitmap->IsAlphaMask()) { return; } m_pDevice->SetDIBits(pDIBitmap, rect.left, rect.top, blend_mode); } if (bClone) { delete pClone; } } return; } int back_left, back_top; FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), top + pDIBitmap->GetHeight()); nonstd::unique_ptr<CFX_DIBitmap> pBackdrop( GetBackdrop(m_pCurObj, rect, back_left, back_top, blend_mode > FXDIB_BLEND_NORMAL && bIsolated)); if (!pBackdrop) return; if (!pDIBitmap->IsAlphaMask()) { pBackdrop->CompositeBitmap(left - back_left, top - back_top, pDIBitmap->GetWidth(), pDIBitmap->GetHeight(), pDIBitmap, 0, 0, blend_mode); } else { pBackdrop->CompositeMask(left - back_left, top - back_top, pDIBitmap->GetWidth(), pDIBitmap->GetHeight(), pDIBitmap, mask_argb, 0, 0, blend_mode); } nonstd::unique_ptr<CFX_DIBitmap> pBackdrop1(new CFX_DIBitmap); pBackdrop1->Create(pBackdrop->GetWidth(), pBackdrop->GetHeight(), FXDIB_Rgb32); pBackdrop1->Clear((FX_DWORD)-1); pBackdrop1->CompositeBitmap(0, 0, pBackdrop->GetWidth(), pBackdrop->GetHeight(), pBackdrop.get(), 0, 0); pBackdrop = nonstd::move(pBackdrop1); m_pDevice->SetDIBits(pBackdrop.get(), back_left, back_top); }
DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc, FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y, int rotate, int flags) { if (page==NULL) return; CPDF_Page* pPage = (CPDF_Page*)page; CRenderContext* pContext = new CRenderContext; pPage->SetPrivateData((void*)1, pContext, DropContext); #ifndef _WIN32_WCE CFX_DIBitmap* pBitmap = NULL; FX_BOOL bBackgroundAlphaNeeded=FALSE; bBackgroundAlphaNeeded = pPage->BackgroundAlphaNeeded(); if (bBackgroundAlphaNeeded) { pBitmap = new CFX_DIBitmap; pBitmap->Create(size_x, size_y, FXDIB_Argb); pBitmap->Clear(0x00ffffff); #ifdef _SKIA_SUPPORT_ pContext->m_pDevice = new CFX_SkiaDevice; ((CFX_SkiaDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap); #else pContext->m_pDevice = new CFX_FxgeDevice; ((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap); #endif } else pContext->m_pDevice = new CFX_WindowsDevice(dc); Func_RenderPage(pContext, page, start_x, start_y, size_x, size_y, rotate, flags,TRUE,NULL); if (bBackgroundAlphaNeeded) { if (pBitmap) { CFX_WindowsDevice WinDC(dc); if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) { CFX_DIBitmap* pDst = new CFX_DIBitmap; int pitch = pBitmap->GetPitch(); pDst->Create(size_x, size_y, FXDIB_Rgb32); FXSYS_memset(pDst->GetBuffer(), -1, pitch*size_y); pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0, FXDIB_BLEND_NORMAL, NULL, FALSE, NULL); WinDC.StretchDIBits(pDst,0,0,size_x,size_y); delete pDst; } else WinDC.SetDIBits(pBitmap,0,0); } } #else // get clip region RECT rect, cliprect; rect.left = start_x; rect.top = start_y; rect.right = start_x + size_x; rect.bottom = start_y + size_y; GetClipBox(dc, &cliprect); IntersectRect(&rect, &rect, &cliprect); int width = rect.right - rect.left; int height = rect.bottom - rect.top; #ifdef DEBUG_TRACE { char str[128]; memset(str, 0, sizeof(str)); FXSYS_snprintf(str, sizeof(str) - 1, "Rendering DIB %d x %d", width, height); CPDF_ModuleMgr::Get()->ReportError(999, str); } #endif // Create a DIB section LPVOID pBuffer; BITMAPINFOHEADER bmih; FXSYS_memset(&bmih, 0, sizeof bmih); bmih.biSize = sizeof bmih; bmih.biBitCount = 24; bmih.biHeight = -height; bmih.biPlanes = 1; bmih.biWidth = width; pContext->m_hBitmap = CreateDIBSection(dc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, &pBuffer, NULL, 0); if (pContext->m_hBitmap == NULL) { #if defined(DEBUG) || defined(_DEBUG) char str[128]; memset(str, 0, sizeof(str)); FXSYS_snprintf(str, sizeof(str) - 1, "Error CreateDIBSection: %d x %d, error code = %d", width, height, GetLastError()); CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, str); #else CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, NULL); #endif } FXSYS_memset(pBuffer, 0xff, height*((width*3+3)/4*4)); #ifdef DEBUG_TRACE { CPDF_ModuleMgr::Get()->ReportError(999, "DIBSection created"); } #endif // Create a device with this external buffer pContext->m_pBitmap = new CFX_DIBitmap; pContext->m_pBitmap->Create(width, height, FXDIB_Rgb, (uint8_t*)pBuffer); pContext->m_pDevice = new CPDF_FxgeDevice; ((CPDF_FxgeDevice*)pContext->m_pDevice)->Attach(pContext->m_pBitmap); #ifdef DEBUG_TRACE CPDF_ModuleMgr::Get()->ReportError(999, "Ready for PDF rendering"); #endif // output to bitmap device Func_RenderPage(pContext, page, start_x - rect.left, start_y - rect.top, size_x, size_y, rotate, flags); #ifdef DEBUG_TRACE CPDF_ModuleMgr::Get()->ReportError(999, "Finished PDF rendering"); #endif // Now output to real device HDC hMemDC = CreateCompatibleDC(dc); if (hMemDC == NULL) { #if defined(DEBUG) || defined(_DEBUG) char str[128]; memset(str, 0, sizeof(str)); FXSYS_snprintf(str, sizeof(str) - 1, "Error CreateCompatibleDC. Error code = %d", GetLastError()); CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, str); #else CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, NULL); #endif } HGDIOBJ hOldBitmap = SelectObject(hMemDC, pContext->m_hBitmap); #ifdef DEBUG_TRACE CPDF_ModuleMgr::Get()->ReportError(999, "Ready for screen rendering"); #endif BitBlt(dc, rect.left, rect.top, width, height, hMemDC, 0, 0, SRCCOPY); SelectObject(hMemDC, hOldBitmap); DeleteDC(hMemDC); #ifdef DEBUG_TRACE CPDF_ModuleMgr::Get()->ReportError(999, "Finished screen rendering"); #endif #endif if (bBackgroundAlphaNeeded) { delete pBitmap; pBitmap = NULL; } delete pContext; pPage->RemovePrivateData((void*)1); }