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 CFFL_InteractiveFormFiller::QueryWherePopup( const CPWL_Wnd::PrivateData* pAttached, float fPopupMin, float fPopupMax, bool* bBottom, float* fPopupRet) { auto* pData = static_cast<const CFFL_PrivateData*>(pAttached); CPDFSDK_Widget* pWidget = pData->pWidget; CPDF_Page* pPage = pWidget->GetPDFPage(); CFX_FloatRect rcPageView(0, pPage->GetPageHeight(), pPage->GetPageWidth(), 0); rcPageView.Normalize(); CFX_FloatRect rcAnnot = pWidget->GetRect(); float fTop = 0.0f; float fBottom = 0.0f; switch (pWidget->GetRotate() / 90) { default: case 0: fTop = rcPageView.top - rcAnnot.top; fBottom = rcAnnot.bottom - rcPageView.bottom; break; case 1: fTop = rcAnnot.left - rcPageView.left; fBottom = rcPageView.right - rcAnnot.right; break; case 2: fTop = rcAnnot.bottom - rcPageView.bottom; fBottom = rcPageView.top - rcAnnot.top; break; case 3: fTop = rcPageView.right - rcAnnot.right; fBottom = rcAnnot.left - rcPageView.left; break; } constexpr float kMaxListBoxHeight = 140; const float fMaxListBoxHeight = pdfium::clamp(kMaxListBoxHeight, fPopupMin, fPopupMax); if (fBottom > fMaxListBoxHeight) { *fPopupRet = fMaxListBoxHeight; *bBottom = true; return; } if (fTop > fMaxListBoxHeight) { *fPopupRet = fMaxListBoxHeight; *bBottom = false; return; } if (fTop > fBottom) { *fPopupRet = fTop; *bBottom = false; } else { *fPopupRet = fBottom; *bBottom = true; } }
static void CheckRotate(CPDF_Page& page, CFX_FloatRect& page_bbox) { int total_count = 0, rotated_count[3] = {0, 0, 0}; FX_POSITION pos = page.GetFirstObjectPosition(); while (pos) { CPDF_PageObject* pObj = page.GetNextObject(pos); if (pObj->m_Type != PDFPAGE_TEXT) { continue; } total_count ++; CPDF_TextObject* pText = (CPDF_TextObject*)pObj; FX_FLOAT angle = pText->m_TextState.GetBaselineAngle(); if (angle == 0.0) { continue; } int degree = (int)(angle * 180 / PI + 0.5); if (degree % 90) { continue; } if (degree < 0) { degree += 360; } int index = degree / 90 % 3 - 1; if (index < 0) { continue; } rotated_count[index] ++; } if (total_count == 0) { return; } CFX_AffineMatrix matrix; if (rotated_count[0] > total_count * 2 / 3) { matrix.Set(0, -1, 1, 0, 0, page.GetPageHeight()); } else if (rotated_count[1] > total_count * 2 / 3) { matrix.Set(-1, 0, 0, -1, page.GetPageWidth(), page.GetPageHeight()); } else if (rotated_count[2] > total_count * 2 / 3) { matrix.Set(0, 1, -1, 0, page.GetPageWidth(), 0); } else { return; } page.Transform(matrix); page_bbox.Transform(&matrix); }
DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document, int page_index, double* width, double* height) { CPDF_Document* pDoc = (CPDF_Document*)document; if(pDoc == NULL) return FALSE; CPDF_Dictionary* pDict = pDoc->GetPage(page_index); if (pDict == NULL) return FALSE; CPDF_Page page; page.Load(pDoc, pDict); *width = page.GetPageWidth(); *height = page.GetPageHeight(); return TRUE; }
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; }