void CFX_PathGenerator::ArcTo(FX_FLOAT x, FX_FLOAT y, FX_FLOAT width, FX_FLOAT height, FX_FLOAT start_angle, FX_FLOAT sweep_angle) { FX_FLOAT x0 = FXSYS_cos(sweep_angle / 2); FX_FLOAT y0 = FXSYS_sin(sweep_angle / 2); FX_FLOAT tx = FXSYS_Div((1.0f - x0) * 4, 3 * 1.0f); FX_FLOAT ty = y0 - FXSYS_Div(FXSYS_Mul(tx, x0), y0); FX_FLOAT px[3], py[3]; px[0] = x0 + tx; py[0] = -ty; px[1] = x0 + tx; py[1] = ty; FX_FLOAT sn = FXSYS_sin(start_angle + sweep_angle / 2); FX_FLOAT cs = FXSYS_cos(start_angle + sweep_angle / 2); int old_count = m_pPathData->GetPointCount(); m_pPathData->AddPointCount(3); FX_FLOAT bezier_x, bezier_y; bezier_x = x + FXSYS_Mul(width, FXSYS_Mul(px[0], cs) - FXSYS_Mul(py[0], sn)); bezier_y = y + FXSYS_Mul(height, FXSYS_Mul(px[0], sn) + FXSYS_Mul(py[0], cs)); m_pPathData->SetPoint(old_count, bezier_x, bezier_y, FXPT_BEZIERTO); bezier_x = x + FXSYS_Mul(width, FXSYS_Mul(px[1], cs) - FXSYS_Mul(py[1], sn)); bezier_y = y + FXSYS_Mul(height, FXSYS_Mul(px[1], sn) + FXSYS_Mul(py[1], cs)); m_pPathData->SetPoint(old_count + 1, bezier_x, bezier_y, FXPT_BEZIERTO); bezier_x = x + FXSYS_Mul(width, FXSYS_cos(start_angle + sweep_angle)), bezier_y = y + FXSYS_Mul(height, FXSYS_sin(start_angle + sweep_angle)); m_pPathData->SetPoint(old_count + 2, bezier_x, bezier_y, FXPT_BEZIERTO); }
void CPDF_Page::GetDisplayMatrix(CFX_Matrix& matrix, int xPos, int yPos, int xSize, int ySize, int iRotate) const { if (m_PageWidth == 0 || m_PageHeight == 0) { return; } CFX_Matrix 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); }
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; }
static void _UpdateLineJoinPoints(CFX_FloatRect& rect, FX_FLOAT start_x, FX_FLOAT start_y, FX_FLOAT middle_x, FX_FLOAT middle_y, FX_FLOAT end_x, FX_FLOAT end_y, FX_FLOAT half_width, FX_FLOAT miter_limit) { FX_FLOAT start_k = 0, start_c = 0, end_k = 0, end_c = 0, start_len = 0, start_dc = 0, end_len = 0, end_dc = 0; FX_BOOL bStartVert = FXSYS_fabs(start_x - middle_x) < 1.0f / 20; FX_BOOL bEndVert = FXSYS_fabs(middle_x - end_x) < 1.0f / 20; if (bStartVert && bEndVert) { int start_dir = middle_y > start_y ? 1 : -1; FX_FLOAT point_y = middle_y + half_width * start_dir; rect.UpdateRect(middle_x + half_width, point_y); rect.UpdateRect(middle_x - half_width, point_y); return; } if (!bStartVert) { start_k = FXSYS_Div(middle_y - start_y, middle_x - start_x); start_c = middle_y - FXSYS_Mul(start_k, middle_x); start_len = FXSYS_sqrt2(start_x - middle_x, start_y - middle_y); start_dc = (FX_FLOAT)FXSYS_fabs( FXSYS_MulDiv(half_width, start_len, start_x - middle_x)); } if (!bEndVert) { end_k = FXSYS_Div(end_y - middle_y, end_x - middle_x); end_c = middle_y - FXSYS_Mul(end_k, middle_x); end_len = FXSYS_sqrt2(end_x - middle_x, end_y - middle_y); end_dc = (FX_FLOAT)FXSYS_fabs( FXSYS_MulDiv(half_width, end_len, end_x - middle_x)); } if (bStartVert) { FX_FLOAT outside_x = start_x; if (end_x < start_x) { outside_x += half_width; } else { outside_x -= half_width; } FX_FLOAT outside_y; if (start_y < FXSYS_Mul(end_k, start_x) + end_c) { outside_y = FXSYS_Mul(end_k, outside_x) + end_c + end_dc; } else { outside_y = FXSYS_Mul(end_k, outside_x) + end_c - end_dc; } rect.UpdateRect(outside_x, outside_y); return; } if (bEndVert) { FX_FLOAT outside_x = end_x; if (start_x < end_x) { outside_x += half_width; } else { outside_x -= half_width; } FX_FLOAT outside_y; if (end_y < FXSYS_Mul(start_k, end_x) + start_c) { outside_y = FXSYS_Mul(start_k, outside_x) + start_c + start_dc; } else { outside_y = FXSYS_Mul(start_k, outside_x) + start_c - start_dc; } rect.UpdateRect(outside_x, outside_y); return; } if (FXSYS_fabs(start_k - end_k) < 1.0f / 20) { int start_dir = middle_x > start_x ? 1 : -1; int end_dir = end_x > middle_x ? 1 : -1; if (start_dir == end_dir) { _UpdateLineEndPoints(rect, middle_x, middle_y, end_x, end_y, half_width); } else { _UpdateLineEndPoints(rect, start_x, start_y, middle_x, middle_y, half_width); } return; } FX_FLOAT start_outside_c = start_c; if (end_y < FXSYS_Mul(start_k, end_x) + start_c) { start_outside_c += start_dc; } else { start_outside_c -= start_dc; } FX_FLOAT end_outside_c = end_c; if (start_y < FXSYS_Mul(end_k, start_x) + end_c) { end_outside_c += end_dc; } else { end_outside_c -= end_dc; } FX_FLOAT join_x = FXSYS_Div(end_outside_c - start_outside_c, start_k - end_k); FX_FLOAT join_y = FXSYS_Mul(start_k, join_x) + start_outside_c; rect.UpdateRect(join_x, join_y); }
static CFX_DIBitmap* Transform1bppBitmap(const CFX_DIBSource* pSrc, const CFX_AffineMatrix* pDestMatrix) { ASSERT(pSrc->GetFormat() == FXDIB_1bppRgb || pSrc->GetFormat() == FXDIB_1bppMask || pSrc->GetFormat() == FXDIB_1bppCmyk); CFX_DIBExtractor src_bitmap(pSrc); CFX_DIBitmap* pSrcBitmap = src_bitmap; if (pSrcBitmap == NULL) { return NULL; } int src_width = pSrcBitmap->GetWidth(), src_height = pSrcBitmap->GetHeight(); uint8_t* src_buf = pSrcBitmap->GetBuffer(); FX_DWORD src_pitch = pSrcBitmap->GetPitch(); FX_FLOAT dest_area = pDestMatrix->GetUnitArea(); FX_FLOAT area_scale = FXSYS_Div((FX_FLOAT)(src_width * src_height), dest_area); FX_FLOAT size_scale = FXSYS_sqrt(area_scale); CFX_AffineMatrix adjusted_matrix(*pDestMatrix); adjusted_matrix.Scale(size_scale, size_scale); CFX_FloatRect result_rect_f = adjusted_matrix.GetUnitRect(); FX_RECT result_rect = result_rect_f.GetOutterRect(); CFX_AffineMatrix src2result; src2result.e = adjusted_matrix.c + adjusted_matrix.e; src2result.f = adjusted_matrix.d + adjusted_matrix.f; src2result.a = adjusted_matrix.a / pSrcBitmap->GetWidth(); src2result.b = adjusted_matrix.b / pSrcBitmap->GetWidth(); src2result.c = -adjusted_matrix.c / pSrcBitmap->GetHeight(); src2result.d = -adjusted_matrix.d / pSrcBitmap->GetHeight(); src2result.TranslateI(-result_rect.left, -result_rect.top); CFX_AffineMatrix result2src; result2src.SetReverse(src2result); CPDF_FixedMatrix result2src_fix(result2src, 8); int result_width = result_rect.Width(); int result_height = result_rect.Height(); CFX_DIBitmap* pTempBitmap = new CFX_DIBitmap; if (!pTempBitmap->Create(result_width, result_height, pSrc->GetFormat())) { delete pTempBitmap; if (pSrcBitmap != src_bitmap) { delete pSrcBitmap; } return NULL; } pTempBitmap->CopyPalette(pSrc->GetPalette()); uint8_t* dest_buf = pTempBitmap->GetBuffer(); int dest_pitch = pTempBitmap->GetPitch(); FXSYS_memset(dest_buf, pSrc->IsAlphaMask() ? 0 : 0xff, dest_pitch * result_height); if (pSrcBitmap->IsAlphaMask()) { for (int dest_y = 0; dest_y < result_height; dest_y++) { uint8_t* dest_scan = dest_buf + dest_y * dest_pitch; for (int dest_x = 0; dest_x < result_width; dest_x++) { int src_x, src_y; result2src_fix.Transform(dest_x, dest_y, src_x, src_y); if (src_x < 0 || src_x >= src_width || src_y < 0 || src_y >= src_height) { continue; } if (!((src_buf + src_pitch * src_y)[src_x / 8] & (1 << (7 - src_x % 8)))) { continue; } dest_scan[dest_x / 8] |= 1 << (7 - dest_x % 8); } } } else { for (int dest_y = 0; dest_y < result_height; dest_y++) { uint8_t* dest_scan = dest_buf + dest_y * dest_pitch; for (int dest_x = 0; dest_x < result_width; dest_x++) { int src_x, src_y; result2src_fix.Transform(dest_x, dest_y, src_x, src_y); if (src_x < 0 || src_x >= src_width || src_y < 0 || src_y >= src_height) { continue; } if ((src_buf + src_pitch * src_y)[src_x / 8] & (1 << (7 - src_x % 8))) { continue; } dest_scan[dest_x / 8] &= ~(1 << (7 - dest_x % 8)); } } } if (pSrcBitmap != src_bitmap) { delete pSrcBitmap; } return pTempBitmap; }
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; }
static void DrawAxialShading(CFX_DIBitmap* pBitmap, CFX_Matrix* pObject2Bitmap, CPDF_Dictionary* pDict, CPDF_Function** pFuncs, int nFuncs, CPDF_ColorSpace* pCS, int alpha) { ASSERT(pBitmap->GetFormat() == FXDIB_Argb); CPDF_Array* pCoords = pDict->GetArray("Coords"); if (!pCoords) { return; } FX_FLOAT start_x = pCoords->GetNumber(0); FX_FLOAT start_y = pCoords->GetNumber(1); FX_FLOAT end_x = pCoords->GetNumber(2); FX_FLOAT end_y = pCoords->GetNumber(3); FX_FLOAT t_min = 0, t_max = 1.0f; CPDF_Array* pArray = pDict->GetArray("Domain"); if (pArray) { t_min = pArray->GetNumber(0); t_max = pArray->GetNumber(1); } FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE; pArray = pDict->GetArray("Extend"); if (pArray) { bStartExtend = pArray->GetInteger(0); bEndExtend = pArray->GetInteger(1); } int width = pBitmap->GetWidth(); int height = pBitmap->GetHeight(); FX_FLOAT x_span = end_x - start_x; FX_FLOAT y_span = end_y - start_y; FX_FLOAT axis_len_square = FXSYS_Mul(x_span, x_span) + FXSYS_Mul(y_span, y_span); CFX_Matrix matrix; matrix.SetReverse(*pObject2Bitmap); int total_results = 0; for (int j = 0; j < nFuncs; j++) { if (pFuncs[j]) { total_results += pFuncs[j]->CountOutputs(); } } if (pCS->CountComponents() > total_results) { total_results = pCS->CountComponents(); } CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results); FX_FLOAT* pResults = result_array; FXSYS_memset(pResults, 0, total_results * sizeof(FX_FLOAT)); FX_DWORD rgb_array[SHADING_STEPS]; for (int i = 0; i < SHADING_STEPS; i++) { FX_FLOAT input = (t_max - t_min) * i / SHADING_STEPS + t_min; int offset = 0; for (int j = 0; j < nFuncs; j++) { if (pFuncs[j]) { int nresults = 0; if (pFuncs[j]->Call(&input, 1, pResults + offset, nresults)) { offset += nresults; } } } FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; pCS->GetRGB(pResults, R, G, B); rgb_array[i] = FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255))); } int pitch = pBitmap->GetPitch(); for (int row = 0; row < height; row++) { FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch); for (int column = 0; column < width; column++) { FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row; matrix.Transform(x, y); FX_FLOAT scale = FXSYS_Div( FXSYS_Mul(x - start_x, x_span) + FXSYS_Mul(y - start_y, y_span), axis_len_square); int index = (int32_t)(scale * (SHADING_STEPS - 1)); if (index < 0) { if (!bStartExtend) { continue; } index = 0; } else if (index >= SHADING_STEPS) { if (!bEndExtend) { continue; } index = SHADING_STEPS - 1; } dib_buf[column] = rgb_array[index]; } } }
static void DrawRadialShading(CFX_DIBitmap* pBitmap, CFX_Matrix* pObject2Bitmap, CPDF_Dictionary* pDict, CPDF_Function** pFuncs, int nFuncs, CPDF_ColorSpace* pCS, int alpha) { ASSERT(pBitmap->GetFormat() == FXDIB_Argb); CPDF_Array* pCoords = pDict->GetArray("Coords"); if (!pCoords) { return; } FX_FLOAT start_x = pCoords->GetNumber(0); FX_FLOAT start_y = pCoords->GetNumber(1); FX_FLOAT start_r = pCoords->GetNumber(2); FX_FLOAT end_x = pCoords->GetNumber(3); FX_FLOAT end_y = pCoords->GetNumber(4); FX_FLOAT end_r = pCoords->GetNumber(5); CFX_Matrix matrix; matrix.SetReverse(*pObject2Bitmap); FX_FLOAT t_min = 0, t_max = 1.0f; CPDF_Array* pArray = pDict->GetArray("Domain"); if (pArray) { t_min = pArray->GetNumber(0); t_max = pArray->GetNumber(1); } FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE; pArray = pDict->GetArray("Extend"); if (pArray) { bStartExtend = pArray->GetInteger(0); bEndExtend = pArray->GetInteger(1); } int total_results = 0; for (int j = 0; j < nFuncs; j++) { if (pFuncs[j]) { total_results += pFuncs[j]->CountOutputs(); } } if (pCS->CountComponents() > total_results) { total_results = pCS->CountComponents(); } CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results); FX_FLOAT* pResults = result_array; FXSYS_memset(pResults, 0, total_results * sizeof(FX_FLOAT)); FX_DWORD rgb_array[SHADING_STEPS]; for (int i = 0; i < SHADING_STEPS; i++) { FX_FLOAT input = (t_max - t_min) * i / SHADING_STEPS + t_min; int offset = 0; for (int j = 0; j < nFuncs; j++) { if (pFuncs[j]) { int nresults; if (pFuncs[j]->Call(&input, 1, pResults + offset, nresults)) { offset += nresults; } } } FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; pCS->GetRGB(pResults, R, G, B); rgb_array[i] = FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255), FXSYS_round(G * 255), FXSYS_round(B * 255))); } FX_FLOAT a = FXSYS_Mul(start_x - end_x, start_x - end_x) + FXSYS_Mul(start_y - end_y, start_y - end_y) - FXSYS_Mul(start_r - end_r, start_r - end_r); int width = pBitmap->GetWidth(); int height = pBitmap->GetHeight(); int pitch = pBitmap->GetPitch(); FX_BOOL bDecreasing = FALSE; if (start_r > end_r) { int length = (int)FXSYS_sqrt((FXSYS_Mul(start_x - end_x, start_x - end_x) + FXSYS_Mul(start_y - end_y, start_y - end_y))); if (length < start_r - end_r) { bDecreasing = TRUE; } } for (int row = 0; row < height; row++) { FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch); for (int column = 0; column < width; column++) { FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row; matrix.Transform(x, y); FX_FLOAT b = -2 * (FXSYS_Mul(x - start_x, end_x - start_x) + FXSYS_Mul(y - start_y, end_y - start_y) + FXSYS_Mul(start_r, end_r - start_r)); FX_FLOAT c = FXSYS_Mul(x - start_x, x - start_x) + FXSYS_Mul(y - start_y, y - start_y) - FXSYS_Mul(start_r, start_r); FX_FLOAT s; if (a == 0) { s = FXSYS_Div(-c, b); } else { FX_FLOAT b2_4ac = FXSYS_Mul(b, b) - 4 * FXSYS_Mul(a, c); if (b2_4ac < 0) { continue; } FX_FLOAT root = FXSYS_sqrt(b2_4ac); FX_FLOAT s1, s2; if (a > 0) { s1 = FXSYS_Div(-b - root, 2 * a); s2 = FXSYS_Div(-b + root, 2 * a); } else { s2 = FXSYS_Div(-b - root, 2 * a); s1 = FXSYS_Div(-b + root, 2 * a); } if (bDecreasing) { if (s1 >= 0 || bStartExtend) { s = s1; } else { s = s2; } } else { if (s2 <= 1.0f || bEndExtend) { s = s2; } else { s = s1; } } if ((start_r + s * (end_r - start_r)) < 0) { continue; } } int index = (int32_t)(s * (SHADING_STEPS - 1)); if (index < 0) { if (!bStartExtend) { continue; } index = 0; } if (index >= SHADING_STEPS) { if (!bEndExtend) { continue; } index = SHADING_STEPS - 1; } dib_buf[column] = rgb_array[index]; } } }
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; } } }
void CWeightTable::Calc(int dest_len, int dest_min, int dest_max, int src_len, int src_min, int src_max, int flags) { if (m_pWeightTables) { FX_Free(m_pWeightTables); m_pWeightTables = NULL; } double scale, base; scale = FXSYS_Div((FX_FLOAT)(src_len), (FX_FLOAT)(dest_len)); if (dest_len < 0) { base = (FX_FLOAT)(src_len); } else { base = 0; } int ext_size = flags & FXDIB_BICUBIC_INTERPOL ? 3 : 1; m_ItemSize = sizeof(int) * 2 + (int)(sizeof(int) * (FXSYS_ceil(FXSYS_fabs((FX_FLOAT)scale)) + ext_size)); m_DestMin = dest_min; if ((dest_max - dest_min) > (int)((1U << 30) - 4) / m_ItemSize) { return; } m_pWeightTables = FX_AllocNL(FX_BYTE, (dest_max - dest_min) * m_ItemSize + 4); if (m_pWeightTables == NULL) { return; } if ((flags & FXDIB_NOSMOOTH) != 0 || FXSYS_fabs((FX_FLOAT)scale) < 1.0f) { for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel ++) { PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); double src_pos = dest_pixel * scale + scale / 2 + base; if (flags & FXDIB_INTERPOL) { pixel_weights.m_SrcStart = (int)FXSYS_floor((FX_FLOAT)src_pos - 1.0f / 2); pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos + 1.0f / 2); if (pixel_weights.m_SrcStart < src_min) { pixel_weights.m_SrcStart = src_min; } if (pixel_weights.m_SrcEnd >= src_max) { pixel_weights.m_SrcEnd = src_max - 1; } if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { pixel_weights.m_Weights[0] = 65536; } else { pixel_weights.m_Weights[1] = FXSYS_round((FX_FLOAT)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * 65536); pixel_weights.m_Weights[0] = 65536 - pixel_weights.m_Weights[1]; } } else if (flags & FXDIB_BICUBIC_INTERPOL) { pixel_weights.m_SrcStart = (int)FXSYS_floor((FX_FLOAT)src_pos - 1.0f / 2); pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos + 1.0f / 2); int start = pixel_weights.m_SrcStart - 1; int end = pixel_weights.m_SrcEnd + 1; if (start < src_min) { start = src_min; } if (end >= src_max) { end = src_max - 1; } if (pixel_weights.m_SrcStart < src_min) { src_pos += src_min - pixel_weights.m_SrcStart; pixel_weights.m_SrcStart = src_min; } if (pixel_weights.m_SrcEnd >= src_max) { pixel_weights.m_SrcEnd = src_max - 1; } int weight; weight = FXSYS_round((FX_FLOAT)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * 256); if (start == end) { pixel_weights.m_Weights[0] = (SDP_Table[256 + weight] + SDP_Table[weight] + SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8; } else if ((start == pixel_weights.m_SrcStart && (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd || end == pixel_weights.m_SrcEnd) && start < end) || (start < pixel_weights.m_SrcStart && pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd && end == pixel_weights.m_SrcEnd)) { if (start < pixel_weights.m_SrcStart) { pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; pixel_weights.m_Weights[1] = (SDP_Table[weight] + SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8; } else { if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { pixel_weights.m_Weights[0] = (SDP_Table[256 + weight] + SDP_Table[weight] + SDP_Table[256 - weight]) << 8; pixel_weights.m_Weights[1] = SDP_Table[512 - weight] << 8; } else { pixel_weights.m_Weights[0] = (SDP_Table[256 + weight] + SDP_Table[weight]) << 8; pixel_weights.m_Weights[1] = (SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8; } } if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { pixel_weights.m_SrcEnd = end; } if (start < pixel_weights.m_SrcStart) { pixel_weights.m_SrcStart = start; } } else if (start == pixel_weights.m_SrcStart && start < pixel_weights.m_SrcEnd && pixel_weights.m_SrcEnd < end) { pixel_weights.m_Weights[0] = (SDP_Table[256 + weight] + SDP_Table[weight]) << 8; pixel_weights.m_Weights[1] = SDP_Table[256 - weight] << 8; pixel_weights.m_Weights[2] = SDP_Table[512 - weight] << 8; pixel_weights.m_SrcEnd = end; } else if (start < pixel_weights.m_SrcStart && pixel_weights.m_SrcStart < pixel_weights.m_SrcEnd && pixel_weights.m_SrcEnd == end) { pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; pixel_weights.m_Weights[1] = SDP_Table[weight] << 8; pixel_weights.m_Weights[2] = (SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8; pixel_weights.m_SrcStart = start; } else { pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; pixel_weights.m_Weights[1] = SDP_Table[weight] << 8; pixel_weights.m_Weights[2] = SDP_Table[256 - weight] << 8; pixel_weights.m_Weights[3] = SDP_Table[512 - weight] << 8; pixel_weights.m_SrcStart = start; pixel_weights.m_SrcEnd = end; } } else { pixel_weights.m_SrcStart = pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos); if (pixel_weights.m_SrcStart < src_min) { pixel_weights.m_SrcStart = src_min; } if (pixel_weights.m_SrcEnd >= src_max) { pixel_weights.m_SrcEnd = src_max - 1; } pixel_weights.m_Weights[0] = 65536; } } return; } for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel ++) { PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); double src_start = dest_pixel * scale + base; double src_end = src_start + scale; int start_i, end_i; if (src_start < src_end) { start_i = (int)FXSYS_floor((FX_FLOAT)src_start); end_i = (int)FXSYS_ceil((FX_FLOAT)src_end); } else { start_i = (int)FXSYS_floor((FX_FLOAT)src_end); end_i = (int)FXSYS_ceil((FX_FLOAT)src_start); } if (start_i < src_min) { start_i = src_min; } if (end_i >= src_max) { end_i = src_max - 1; } if (start_i > end_i) { if (start_i >= src_max) { start_i = src_max - 1; } pixel_weights.m_SrcStart = start_i; pixel_weights.m_SrcEnd = start_i; continue; } pixel_weights.m_SrcStart = start_i; pixel_weights.m_SrcEnd = end_i; for (int j = start_i; j <= end_i; j ++) { double dest_start = FXSYS_Div((FX_FLOAT)(j) - base, scale); double dest_end = FXSYS_Div((FX_FLOAT)(j + 1) - base, scale); if (dest_start > dest_end) { double temp = dest_start; dest_start = dest_end; dest_end = temp; } double area_start = dest_start > (FX_FLOAT)(dest_pixel) ? dest_start : (FX_FLOAT)(dest_pixel); double area_end = dest_end > (FX_FLOAT)(dest_pixel + 1) ? (FX_FLOAT)(dest_pixel + 1) : dest_end; double weight = area_start >= area_end ? 0.0f : area_end - area_start; if (weight == 0 && j == end_i) { pixel_weights.m_SrcEnd --; break; } pixel_weights.m_Weights[j - start_i] = FXSYS_round((FX_FLOAT)(weight * 65536)); } } }