static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex, jlong transformPtr, jint clipLeft, jint clipTop, jint clipRight, jint clipBottom) { FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr); CPDF_Page* page = (CPDF_Page*) FPDF_LoadPage(document, pageIndex); if (!page) { jniThrowException(env, "java/lang/IllegalStateException", "cannot open page"); return; } double width = 0; double height = 0; const int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height); if (!result) { jniThrowException(env, "java/lang/IllegalStateException", "cannot get page size"); return; } CFX_AffineMatrix matrix; SkMatrix* skTransform = reinterpret_cast<SkMatrix*>(transformPtr); SkScalar transformValues[6]; if (!skTransform->asAffine(transformValues)) { jniThrowException(env, "java/lang/IllegalArgumentException", "transform matrix has perspective. Only affine matrices are allowed."); return; } // PDF's coordinate system origin is left-bottom while in graphics it // is the top-left. So, translate the PDF coordinates to ours. matrix.Set(1, 0, 0, -1, 0, page->GetPageHeight()); // Apply the transformation what was created in our coordinates. matrix.Concat(transformValues[SkMatrix::kAScaleX], transformValues[SkMatrix::kASkewY], transformValues[SkMatrix::kASkewX], transformValues[SkMatrix::kAScaleY], transformValues[SkMatrix::kATransX], transformValues[SkMatrix::kATransY]); // Translate the result back to PDF coordinates. matrix.Concat(1, 0, 0, -1, 0, page->GetPageHeight()); FS_MATRIX transform = {matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f}; FS_RECTF clip = {(float) clipLeft, (float) clipTop, (float) clipRight, (float) clipBottom}; FPDFPage_TransFormWithClip(page, &transform, &clip); FPDF_ClosePage(page); }
void CPDF_FormControl::DrawControl(CFX_RenderDevice* pDevice, CFX_AffineMatrix* pMatrix, CPDF_Page* pPage, CPDF_Annot::AppearanceMode mode, const CPDF_RenderOptions* pOptions) { if (m_pWidgetDict->GetInteger("F") & ANNOTFLAG_HIDDEN) { return; } CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(m_pWidgetDict, mode); if (pStream == NULL) { return; } CFX_FloatRect form_bbox = pStream->GetDict()->GetRect("BBox"); CFX_AffineMatrix form_matrix = pStream->GetDict()->GetMatrix("Matrix"); form_matrix.TransformRect(form_bbox); CFX_FloatRect arect = m_pWidgetDict->GetRect("Rect"); CFX_AffineMatrix matrix; matrix.MatchRect(arect, form_bbox); matrix.Concat(*pMatrix); CPDF_Form form(m_pField->m_pForm->m_pDocument, m_pField->m_pForm->m_pFormDict->GetDict("DR"), pStream); form.ParseContent(NULL, NULL, NULL, NULL); CPDF_RenderContext context; context.Create(pPage); context.DrawObjectList(pDevice, &form, &matrix, pOptions); }
FX_BOOL CPDF_RenderStatus::ProcessForm(CPDF_FormObject* pFormObj, const CFX_AffineMatrix* pObj2Device) { CPDF_Dictionary* pOC = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("OC")); if (pOC && m_Options.m_pOCContext && !m_Options.m_pOCContext->CheckOCGVisible(pOC)) { return TRUE; } CFX_AffineMatrix matrix = pFormObj->m_FormMatrix; matrix.Concat(*pObj2Device); CPDF_Dictionary* pResources = NULL; if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) { pResources = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources")); } CPDF_RenderStatus status; status.Initialize(m_pContext, m_pDevice, NULL, m_pStopObj, this, pFormObj, &m_Options, m_Transparency, m_bDropObjects, pResources, FALSE); status.m_curBlend = m_curBlend; m_pDevice->SaveState(); status.RenderObjectList(pFormObj->m_pForm, &matrix); m_bStopped = status.m_bStopped; m_pDevice->RestoreState(); return TRUE; }
void CPDF_RenderStatus::DrawObjWithBackground( const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device) { FX_RECT rect; if (GetObjectClippedRect(pObj, pObj2Device, FALSE, rect)) { return; } int res = 300; if (pObj->m_Type == PDFPAGE_IMAGE && m_pDevice->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) { res = 0; } CPDF_ScaledRenderBuffer buffer; if (!buffer.Initialize(m_pContext, m_pDevice, &rect, pObj, &m_Options, res)) { return; } CFX_AffineMatrix matrix = *pObj2Device; matrix.Concat(*buffer.GetMatrix()); GetScaledMatrix(matrix); CPDF_Dictionary* pFormResource = NULL; if (pObj->m_Type == PDFPAGE_FORM) { CPDF_FormObject* pFormObj = (CPDF_FormObject*)pObj; if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) { pFormResource = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources")); } } CPDF_RenderStatus status; status.Initialize(m_pContext, buffer.GetDevice(), buffer.GetMatrix(), NULL, NULL, NULL, &m_Options, m_Transparency, m_bDropObjects, pFormResource); status.RenderSingleObject(pObj, &matrix); buffer.OutputToDevice(); }
void CPDF_RenderStatus::DrawShadingPattern(CPDF_ShadingPattern* pattern, CPDF_PageObject* pPageObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke) { if (!pattern->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 rect; if (GetObjectClippedRect(pPageObj, pObj2Device, FALSE, rect)) { m_pDevice->RestoreState(); return; } CFX_AffineMatrix matrix = pattern->m_Pattern2Form; matrix.Concat(*pObj2Device); GetScaledMatrix(matrix); int alpha = pPageObj->m_GeneralState.GetAlpha(bStroke); DrawShading(pattern, &matrix, rect, alpha, m_Options.m_ColorMode == RENDER_COLOR_ALPHA); m_pDevice->RestoreState(); }
void CPDF_RenderStatus::DrawTextPathWithPattern( const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device, CPDF_Font* pFont, FX_FLOAT font_size, const CFX_AffineMatrix* pTextMatrix, FX_BOOL bFill, FX_BOOL bStroke) { if (!bStroke) { CPDF_PathObject path; CPDF_TextObject* pCopy = new CPDF_TextObject; pCopy->Copy(textobj); path.m_bStroke = FALSE; path.m_FillType = FXFILL_WINDING; path.m_ClipPath.AppendTexts(&pCopy, 1); path.m_ColorState = textobj->m_ColorState; path.m_Path.New()->AppendRect(textobj->m_Left, textobj->m_Bottom, textobj->m_Right, textobj->m_Top); path.m_Left = textobj->m_Left; path.m_Bottom = textobj->m_Bottom; path.m_Right = textobj->m_Right; path.m_Top = textobj->m_Top; RenderSingleObject(&path, pObj2Device); return; } CFX_FontCache* pCache; if (pFont->m_pDocument) { pCache = pFont->m_pDocument->GetRenderData()->GetFontCache(); } else { pCache = CFX_GEModule::Get()->GetFontCache(); } CFX_FaceCache* pFaceCache = pCache->GetCachedFace(&pFont->m_Font); FX_FONTCACHE_DEFINE(pCache, &pFont->m_Font); CPDF_CharPosList CharPosList; CharPosList.Load(textobj->m_nChars, textobj->m_pCharCodes, textobj->m_pCharPos, pFont, font_size); for (FX_DWORD i = 0; i < CharPosList.m_nChars; i++) { FXTEXT_CHARPOS& charpos = CharPosList.m_pCharPos[i]; const CFX_PathData* pPath = pFaceCache->LoadGlyphPath( &pFont->m_Font, charpos.m_GlyphIndex, charpos.m_FontCharWidth); if (pPath == NULL) { continue; } CPDF_PathObject path; path.m_GraphState = textobj->m_GraphState; path.m_ColorState = textobj->m_ColorState; CFX_AffineMatrix matrix; if (charpos.m_bGlyphAdjust) matrix.Set(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0); matrix.Concat(font_size, 0, 0, font_size, charpos.m_OriginX, charpos.m_OriginY); path.m_Path.New()->Append(pPath, &matrix); path.m_Matrix = *pTextMatrix; path.m_bStroke = bStroke; path.m_FillType = bFill ? FXFILL_WINDING : 0; path.CalcBoundingBox(); ProcessPath(&path, pObj2Device); } }
void CPDF_ReflowedPage::GetDisplayMatrix(CFX_AffineMatrix& matrix, FX_INT32 xPos, FX_INT32 yPos, FX_INT32 xSize, FX_INT32 ySize, FX_INT32 iRotate, const CFX_AffineMatrix* pPageMatrix) { CFX_AffineMatrix display_matrix; if(m_PageHeight == 0) { matrix.Set(1, 0, 0, -1, 0, 0); return; } FX_INT32 x0, y0, x1, y1, x2, y2; iRotate %= 4; switch (iRotate) { case 0: x0 = xPos; y0 = yPos; x1 = xPos; y1 = yPos + ySize; x2 = xPos + xSize; y2 = yPos; break; case 3: x0 = xPos; y0 = ySize + yPos; x1 = xPos + xSize; y1 = yPos + ySize; x2 = xPos; y2 = yPos; break; case 2: x0 = xSize + xPos; y0 = ySize + yPos; x1 = xSize + xPos ; y1 = yPos; x2 = xPos; y2 = ySize + yPos; break; case 1: x0 = xPos + xSize; y0 = yPos; x1 = xPos; y1 = yPos; x2 = xPos + xSize; y2 = yPos + ySize; break; } display_matrix.Set(FXSYS_Div((FX_FLOAT)(x2 - x0), m_PageWidth), FXSYS_Div((FX_FLOAT)(y2 - y0), m_PageWidth), FXSYS_Div((FX_FLOAT)(x1 - x0), m_PageHeight), FXSYS_Div((FX_FLOAT)(y1 - y0), m_PageHeight), (FX_FLOAT)(x0), (FX_FLOAT)(y0)); matrix.Set(1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f); matrix.Concat(display_matrix); return; }
void CPDF_Page::GetDisplayMatrix(CFX_AffineMatrix& matrix, int xPos, int yPos, int xSize, int ySize, int iRotate) const { if (m_PageWidth == 0 || m_PageHeight == 0) { return; } CFX_AffineMatrix display_matrix; int x0, y0, x1, y1, x2, y2; iRotate %= 4; switch (iRotate) { case 0: x0 = xPos; y0 = yPos + ySize; x1 = xPos; y1 = yPos; x2 = xPos + xSize; y2 = yPos + ySize; break; case 1: x0 = xPos; y0 = yPos; x1 = xPos + xSize; y1 = yPos; x2 = xPos; y2 = yPos + ySize; break; case 2: x0 = xPos + xSize; y0 = yPos; x1 = xPos + xSize; y1 = yPos + ySize; x2 = xPos; y2 = yPos; break; case 3: x0 = xPos + xSize; y0 = yPos + ySize; x1 = xPos; y1 = yPos + ySize; x2 = xPos + xSize; y2 = yPos; break; } display_matrix.Set(FXSYS_Div((FX_FLOAT)(x2 - x0), m_PageWidth), FXSYS_Div((FX_FLOAT)(y2 - y0), m_PageWidth), FXSYS_Div((FX_FLOAT)(x1 - x0), m_PageHeight), FXSYS_Div((FX_FLOAT)(y1 - y0), m_PageHeight), (FX_FLOAT)x0, (FX_FLOAT)y0); matrix = m_PageMatrix; matrix.Concat(display_matrix); }
FX_BOOL CPDF_RenderStatus::ProcessShading(CPDF_ShadingObject* pShadingObj, const CFX_AffineMatrix* pObj2Device) { FX_RECT rect = pShadingObj->GetBBox(pObj2Device); FX_RECT clip_box = m_pDevice->GetClipBox(); rect.Intersect(clip_box); if (rect.IsEmpty()) { return TRUE; } CFX_AffineMatrix matrix = pShadingObj->m_Matrix; matrix.Concat(*pObj2Device); DrawShading(pShadingObj->m_pShading, &matrix, rect, pShadingObj->m_GeneralState.GetAlpha(FALSE), m_Options.m_ColorMode == RENDER_COLOR_ALPHA); return TRUE; }
void CPDF_StreamContentParser::EndInlineImage() { CFX_AffineMatrix ImageMatrix; ImageMatrix.Copy(m_pCurStates->m_CTM); ImageMatrix.Concat(m_mtContentToUser); m_LastImageData.CopyData(m_ImageSrcBuf.GetBuffer(), m_ImageSrcBuf.GetSize()); CPDF_Stream* pStream = CPDF_Stream::Create(m_ImageSrcBuf.GetBuffer(), m_ImageSrcBuf.GetSize(), m_pLastCloneImageDict); m_ImageSrcBuf.DetachBuffer(); m_pLastCloneImageDict = NULL; CPDF_InlineImages* pImages = FX_NEW CPDF_InlineImages; pImages->m_pStream = pStream; SetGraphicStates(pImages, !m_pLastCloneImageDict->KeyExist(FX_BSTRC("ColorSpace")), FALSE, FALSE); pImages->AddMatrix(ImageMatrix); m_pObjectList->m_ObjectList.AddTail(pImages); m_WordState = 0; }
void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice, const CPDF_PageObject* pStopObj, const CPDF_RenderOptions* pOptions, const CFX_AffineMatrix* pLastMatrix) { int count = m_ContentList.GetSize(); for (int j = 0; j < count; j++) { pDevice->SaveState(); _PDF_RenderItem* pItem = m_ContentList.GetDataPtr(j); if (pLastMatrix) { CFX_AffineMatrix FinalMatrix = pItem->m_Matrix; FinalMatrix.Concat(*pLastMatrix); CPDF_RenderStatus status; status.Initialize(this, pDevice, pLastMatrix, pStopObj, NULL, NULL, pOptions, pItem->m_pObjectList->m_Transparency, FALSE, NULL); status.RenderObjectList(pItem->m_pObjectList, &FinalMatrix); if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) { m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize); } if (status.m_bStopped) { pDevice->RestoreState(); break; } } else { CPDF_RenderStatus status; status.Initialize(this, pDevice, NULL, pStopObj, NULL, NULL, pOptions, pItem->m_pObjectList->m_Transparency, FALSE, NULL); status.RenderObjectList(pItem->m_pObjectList, &pItem->m_Matrix); if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) { m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize); } if (status.m_bStopped) { pDevice->RestoreState(); break; } } pDevice->RestoreState(); } }
static void renderPageBitmap(FPDF_BITMAP bitmap, FPDF_PAGE page, int destLeft, int destTop, int destRight, int destBottom, SkMatrix* transform, int flags) { // Note: this code ignores the currently unused RENDER_NO_NATIVETEXT, // FPDF_RENDER_LIMITEDIMAGECACHE, FPDF_RENDER_FORCEHALFTONE, FPDF_GRAYSCALE, // and FPDF_ANNOT flags. To add support for that refer to FPDF_RenderPage_Retail // in fpdfview.cpp CRenderContext* pContext = FX_NEW CRenderContext; CPDF_Page* pPage = (CPDF_Page*) page; pPage->SetPrivateData((void*) 1, pContext, DropContext); CFX_FxgeDevice* fxgeDevice = FX_NEW CFX_FxgeDevice; pContext->m_pDevice = fxgeDevice; // Reverse the bytes (last argument TRUE) since the Android // format is ARGB while the renderer uses BGRA internally. fxgeDevice->Attach((CFX_DIBitmap*) bitmap, 0, TRUE); CPDF_RenderOptions* renderOptions = pContext->m_pOptions; if (!renderOptions) { renderOptions = FX_NEW CPDF_RenderOptions; pContext->m_pOptions = renderOptions; } if (flags & FPDF_LCD_TEXT) { renderOptions->m_Flags |= RENDER_CLEARTYPE; } else { renderOptions->m_Flags &= ~RENDER_CLEARTYPE; } const CPDF_OCContext::UsageType usage = (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View; renderOptions->m_AddFlags = flags >> 8; renderOptions->m_pOCContext = new CPDF_OCContext(pPage->m_pDocument, usage); fxgeDevice->SaveState(); FX_RECT clip; clip.left = destLeft; clip.right = destRight; clip.top = destTop; clip.bottom = destBottom; fxgeDevice->SetClip_Rect(&clip); CPDF_RenderContext* pageContext = FX_NEW CPDF_RenderContext; pContext->m_pContext = pageContext; pageContext->Create(pPage); CFX_AffineMatrix matrix; if (!transform) { pPage->GetDisplayMatrix(matrix, destLeft, destTop, destRight - destLeft, destBottom - destTop, 0); } else { // PDF's coordinate system origin is left-bottom while // in graphics it is the top-left, so remap the origin. matrix.Set(1, 0, 0, -1, 0, pPage->GetPageHeight()); SkScalar transformValues[6]; transform->asAffine(transformValues); matrix.Concat(transformValues[SkMatrix::kAScaleX], transformValues[SkMatrix::kASkewY], transformValues[SkMatrix::kASkewX], transformValues[SkMatrix::kAScaleY], transformValues[SkMatrix::kATransX], transformValues[SkMatrix::kATransY]); } pageContext->AppendObjectList(pPage, &matrix); pContext->m_pRenderer = FX_NEW CPDF_ProgressiveRenderer; pContext->m_pRenderer->Start(pageContext, fxgeDevice, renderOptions, NULL); fxgeDevice->RestoreState(); pPage->RemovePrivateData((void*) 1); delete pContext; }
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; }
DLLEXPORT FPDF_BOOL STDCALL FPDFPage_TransFormWithClip(FPDF_PAGE page, FS_MATRIX* matrix, FS_RECTF* clipRect) { if(!page) return FALSE; CFX_ByteTextBuf textBuf; textBuf<<"q "; CFX_FloatRect rect(clipRect->left, clipRect->bottom, clipRect->right, clipRect->top); rect.Normalize(); CFX_ByteString bsClipping; bsClipping.Format("%f %f %f %f re W* n ", rect.left, rect.bottom, rect.Width(), rect.Height()); textBuf<<bsClipping; CFX_ByteString bsMatix; bsMatix.Format("%f %f %f %f %f %f cm ", matrix->a, matrix->b,matrix->c,matrix->d,matrix->e,matrix->f); textBuf<<bsMatix; CPDF_Page* pPage = (CPDF_Page*)page; CPDF_Dictionary* pPageDic = pPage->m_pFormDict; CPDF_Object* pContentObj = pPageDic->GetElement("Contents"); if(!pContentObj) pContentObj = pPageDic->GetArray("Contents"); if(!pContentObj) return FALSE; CPDF_Dictionary* pDic = FX_NEW CPDF_Dictionary; CPDF_Stream* pStream = FX_NEW CPDF_Stream(NULL,0, pDic); pStream->SetData(textBuf.GetBuffer(), textBuf.GetSize(), FALSE, FALSE); CPDF_Document* pDoc = pPage->m_pDocument; if(!pDoc) return FALSE; pDoc->AddIndirectObject(pStream); pDic = FX_NEW CPDF_Dictionary; CPDF_Stream* pEndStream = FX_NEW CPDF_Stream(NULL,0, pDic); pEndStream->SetData((FX_LPCBYTE)" Q", 2, FALSE, FALSE); pDoc->AddIndirectObject(pEndStream); CPDF_Array* pContentArray = NULL; if (pContentObj && pContentObj->GetType() == PDFOBJ_ARRAY) { pContentArray = (CPDF_Array*)pContentObj; CPDF_Reference* pRef = FX_NEW CPDF_Reference(pDoc, pStream->GetObjNum()); pContentArray->InsertAt(0, pRef); pContentArray->AddReference(pDoc,pEndStream); } else if(pContentObj && pContentObj->GetType() == PDFOBJ_REFERENCE) { CPDF_Reference* pReference = (CPDF_Reference*)pContentObj; CPDF_Object* pDirectObj = pReference->GetDirect(); if(pDirectObj != NULL) { if(pDirectObj->GetType() == PDFOBJ_ARRAY) { pContentArray = (CPDF_Array*)pDirectObj; CPDF_Reference* pRef = FX_NEW CPDF_Reference(pDoc, pStream->GetObjNum()); pContentArray->InsertAt(0, pRef); pContentArray->AddReference(pDoc,pEndStream); } else if(pDirectObj->GetType() == PDFOBJ_STREAM) { pContentArray = FX_NEW CPDF_Array(); pContentArray->AddReference(pDoc,pStream->GetObjNum()); pContentArray->AddReference(pDoc,pDirectObj->GetObjNum()); pContentArray->AddReference(pDoc, pEndStream); pPageDic->SetAtReference("Contents", pDoc, pDoc->AddIndirectObject(pContentArray)); } } } //Need to transform the patterns as well. CPDF_Dictionary* pRes = pPageDic->GetDict(FX_BSTRC("Resources")); if(pRes) { CPDF_Dictionary* pPattenDict = pRes->GetDict(FX_BSTRC("Pattern")); if(pPattenDict) { FX_POSITION pos = pPattenDict->GetStartPos(); while(pos) { CPDF_Dictionary* pDict = NULL; CFX_ByteString key; CPDF_Object* pObj = pPattenDict->GetNextElement(pos, key); if(pObj->GetType() == PDFOBJ_REFERENCE) pObj = pObj->GetDirect(); if(pObj->GetType() == PDFOBJ_DICTIONARY) { pDict = (CPDF_Dictionary*)pObj; } else if(pObj->GetType() == PDFOBJ_STREAM) { pDict = ((CPDF_Stream*)pObj)->GetDict(); } else continue; CFX_AffineMatrix m = pDict->GetMatrix(FX_BSTRC("Matrix")); CFX_AffineMatrix t = *(CFX_AffineMatrix*)matrix; m.Concat(t); pDict->SetAtMatrix(FX_BSTRC("Matrix"), m); } } } return TRUE; }
void CPDF_RenderStatus::DrawShading(CPDF_ShadingPattern* pPattern, CFX_AffineMatrix* 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 == NULL) { return; } FX_ARGB background = 0; if (!pPattern->m_bShadingObj && pPattern->m_pShadingObj->GetDict()->KeyExist(FX_BSTRC("Background"))) { CPDF_Array* pBackColor = pPattern->m_pShadingObj->GetDict()->GetArray(FX_BSTRC("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(FX_BSTRC("BBox"))) { CFX_FloatRect rect = pDict->GetRect(FX_BSTRC("BBox")); rect.Transform(pMatrix); clip_rect.Intersect(rect.GetOutterRect()); } CPDF_DeviceBuffer buffer; buffer.Initialize(m_pContext, m_pDevice, &clip_rect, m_pCurObj, 150); CFX_AffineMatrix FinalMatrix = *pMatrix; FinalMatrix.Concat(*buffer.GetMatrix()); CFX_DIBitmap* pBitmap = buffer.GetBitmap(); if (pBitmap->GetBuffer() == NULL) { 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(); }
void CFX_PSRenderer::FindPSFontGlyph(CFX_FaceCache* pFaceCache, CFX_Font* pFont, const FXTEXT_CHARPOS& charpos, int& ps_fontnum, int &ps_glyphindex) { for (int i = 0; i < (int)m_PSFontList.GetSize(); i ++) { CPSFont* pPSFont = m_PSFontList[i]; for (int j = 0; j < pPSFont->m_nGlyphs; j ++) if (pPSFont->m_Glyphs[j].m_pFont == pFont && pPSFont->m_Glyphs[j].m_GlyphIndex == charpos.m_GlyphIndex) { if ((!pPSFont->m_Glyphs[j].m_bGlyphAdjust && !charpos.m_bGlyphAdjust) || (pPSFont->m_Glyphs[j].m_bGlyphAdjust && charpos.m_bGlyphAdjust && (FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[0] - charpos.m_AdjustMatrix[0]) < 0.01 && FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[1] - charpos.m_AdjustMatrix[1]) < 0.01 && FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[2] - charpos.m_AdjustMatrix[2]) < 0.01 && FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[3] - charpos.m_AdjustMatrix[3]) < 0.01))) { ps_fontnum = i; ps_glyphindex = j; return; } } } if (m_PSFontList.GetSize() == 0 || m_PSFontList[m_PSFontList.GetSize() - 1]->m_nGlyphs == 256) { CPSFont* pPSFont = new CPSFont; pPSFont->m_nGlyphs = 0; m_PSFontList.Add(pPSFont); CFX_ByteTextBuf buf; buf << FX_BSTRC("8 dict begin/FontType 3 def/FontMatrix[1 0 0 1 0 0]def\n" "/FontBBox[0 0 0 0]def/Encoding 256 array def 0 1 255{Encoding exch/.notdef put}for\n" "/CharProcs 1 dict def CharProcs begin/.notdef {} def end\n" "/BuildGlyph{1 0 -10 -10 10 10 setcachedevice exch/CharProcs get exch 2 copy known not{pop/.notdef}if get exec}bind def\n" "/BuildChar{1 index/Encoding get exch get 1 index/BuildGlyph get exec}bind def\n" "currentdict end\n"); buf << FX_BSTRC("/X") << m_PSFontList.GetSize() - 1 << FX_BSTRC(" exch definefont pop\n"); m_pOutput->OutputPS((FX_LPCSTR)buf.GetBuffer(), buf.GetSize()); buf.Clear(); } ps_fontnum = m_PSFontList.GetSize() - 1; CPSFont* pPSFont = m_PSFontList[ps_fontnum]; ps_glyphindex = pPSFont->m_nGlyphs; pPSFont->m_Glyphs[ps_glyphindex].m_GlyphIndex = charpos.m_GlyphIndex; pPSFont->m_Glyphs[ps_glyphindex].m_pFont = pFont; pPSFont->m_Glyphs[ps_glyphindex].m_bGlyphAdjust = charpos.m_bGlyphAdjust; if (charpos.m_bGlyphAdjust) { pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[0] = charpos.m_AdjustMatrix[0]; pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[1] = charpos.m_AdjustMatrix[1]; pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[2] = charpos.m_AdjustMatrix[2]; pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[3] = charpos.m_AdjustMatrix[3]; } pPSFont->m_nGlyphs ++; CFX_AffineMatrix matrix; if (charpos.m_bGlyphAdjust) matrix.Set(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0); matrix.Concat(1.0f, 0, 0, 1.0f, 0, 0); const CFX_PathData* pPathData = pFaceCache->LoadGlyphPath(pFont, charpos.m_GlyphIndex, charpos.m_FontCharWidth); if (pPathData == NULL) { return; } CFX_PathData TransformedPath(*pPathData); if (charpos.m_bGlyphAdjust) { TransformedPath.Transform(&matrix); } CFX_ByteTextBuf buf; buf << FX_BSTRC("/X") << ps_fontnum << FX_BSTRC(" Ff/CharProcs get begin/") << ps_glyphindex << FX_BSTRC("{"); buf << FX_BSTRC("n "); for (int p = 0; p < TransformedPath.GetPointCount(); p ++) { FX_FLOAT x = TransformedPath.GetPointX(p), y = TransformedPath.GetPointY(p); switch (TransformedPath.GetFlag(p) & FXPT_TYPE) { case FXPT_MOVETO: { buf << x << FX_BSTRC(" ") << y << FX_BSTRC(" m\n"); break; } case FXPT_LINETO: { buf << x << FX_BSTRC(" ") << y << FX_BSTRC(" l\n"); break; } case FXPT_BEZIERTO: { buf << x << FX_BSTRC(" ") << y << FX_BSTRC(" ") << TransformedPath.GetPointX(p + 1) << FX_BSTRC(" ") << TransformedPath.GetPointY(p + 1) << FX_BSTRC(" ") << TransformedPath.GetPointX(p + 2) << FX_BSTRC(" ") << TransformedPath.GetPointY(p + 2) << FX_BSTRC(" c\n"); p += 2; break; } } } buf << FX_BSTRC("f"); buf << FX_BSTRC("}bind def end\n"); buf << FX_BSTRC("/X") << ps_fontnum << FX_BSTRC(" Ff/Encoding get ") << ps_glyphindex << FX_BSTRC("/") << ps_glyphindex << FX_BSTRC(" put\n"); m_pOutput->OutputPS((FX_LPCSTR)buf.GetBuffer(), buf.GetSize()); }