void CFX_PathGenerator::AddPie(FX_FLOAT x, FX_FLOAT y, FX_FLOAT width, FX_FLOAT height, FX_FLOAT start_angle, FX_FLOAT sweep_angle) { if (sweep_angle == 0) { int old_count = m_pPathData->GetPointCount(); m_pPathData->AddPointCount(2); m_pPathData->SetPoint(old_count, x, y, FXPT_MOVETO); m_pPathData->SetPoint( old_count + 1, x + FXSYS_Mul(width, FXSYS_cos(start_angle)), y + FXSYS_Mul(height, FXSYS_sin(start_angle)), FXPT_LINETO); return; } AddArc(x, y, width, height, start_angle, sweep_angle); m_pPathData->AddPointCount(1); m_pPathData->SetPoint(m_pPathData->GetPointCount() - 1, x, y, FXPT_LINETO | FXPT_CLOSEFIGURE); }
void CPDF_StreamContentParser::Handle_ShowText_Positioning() { CPDF_Array* pArray = GetObject(0) ? GetObject(0)->GetArray() : NULL; if (!pArray) { return; } int n = pArray->GetCount(); int nsegs = 0; for (int i = 0; i < n; i++) { if (pArray->GetElementValue(i)->IsString()) nsegs++; } if (nsegs == 0) { for (int i = 0; i < n; i++) { m_pCurStates->m_TextX -= FXSYS_Mul(pArray->GetNumber(i), m_pCurStates->m_TextState.GetFontSize()) / 1000; } return; } CFX_ByteString* pStrs = new CFX_ByteString[nsegs]; FX_FLOAT* pKerning = FX_Alloc(FX_FLOAT, nsegs); int iSegment = 0; FX_FLOAT fInitKerning = 0; for (int i = 0; i < n; i++) { CPDF_Object* pObj = pArray->GetElementValue(i); if (pObj->IsString()) { CFX_ByteString str = pObj->GetString(); if (str.IsEmpty()) { continue; } pStrs[iSegment] = str; pKerning[iSegment++] = 0; } else { FX_FLOAT num = pObj ? pObj->GetNumber() : 0; if (iSegment == 0) { fInitKerning += num; } else { pKerning[iSegment - 1] += num; } } } AddTextObject(pStrs, fInitKerning, pKerning, iSegment); delete[] pStrs; FX_Free(pKerning); }
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 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 CPDF_TextObject::CalcPositionData(FX_FLOAT* pTextAdvanceX, FX_FLOAT* pTextAdvanceY, FX_FLOAT horz_scale, int level) { FX_FLOAT curpos = 0; FX_FLOAT min_x = 10000 * 1.0f; FX_FLOAT max_x = -10000 * 1.0f; FX_FLOAT min_y = 10000 * 1.0f; FX_FLOAT max_y = -10000 * 1.0f; CPDF_Font* pFont = m_TextState.GetFont(); FX_BOOL bVertWriting = FALSE; CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); if (pCIDFont) { bVertWriting = pCIDFont->IsVertWriting(); } FX_FLOAT fontsize = m_TextState.GetFontSize(); for (int i = 0; i < m_nChars; ++i) { FX_DWORD charcode = m_nChars == 1 ? (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[i]; if (charcode == (FX_DWORD) - 1) { curpos -= FXSYS_Mul(m_pCharPos[i - 1], fontsize) / 1000; continue; } if (i) { m_pCharPos[i - 1] = curpos; } FX_RECT char_rect; pFont->GetCharBBox(charcode, char_rect, level); FX_FLOAT charwidth; if (!bVertWriting) { if (min_y > char_rect.top) { min_y = (FX_FLOAT)char_rect.top; } if (max_y < char_rect.top) { max_y = (FX_FLOAT)char_rect.top; } if (min_y > char_rect.bottom) { min_y = (FX_FLOAT)char_rect.bottom; } if (max_y < char_rect.bottom) { max_y = (FX_FLOAT)char_rect.bottom; } FX_FLOAT char_left = curpos + char_rect.left * fontsize / 1000; FX_FLOAT char_right = curpos + char_rect.right * fontsize / 1000; if (min_x > char_left) { min_x = char_left; } if (max_x < char_left) { max_x = char_left; } if (min_x > char_right) { min_x = char_right; } if (max_x < char_right) { max_x = char_right; } charwidth = pFont->GetCharWidthF(charcode, level) * fontsize / 1000; } else { FX_WORD CID = pCIDFont->CIDFromCharCode(charcode); short vx; short vy; pCIDFont->GetVertOrigin(CID, vx, vy); char_rect.left -= vx; char_rect.right -= vx; char_rect.top -= vy; char_rect.bottom -= vy; if (min_x > char_rect.left) { min_x = (FX_FLOAT)char_rect.left; } if (max_x < char_rect.left) { max_x = (FX_FLOAT)char_rect.left; } if (min_x > char_rect.right) { min_x = (FX_FLOAT)char_rect.right; } if (max_x < char_rect.right) { max_x = (FX_FLOAT)char_rect.right; } FX_FLOAT char_top = curpos + char_rect.top * fontsize / 1000; FX_FLOAT char_bottom = curpos + char_rect.bottom * fontsize / 1000; if (min_y > char_top) { min_y = char_top; } if (max_y < char_top) { max_y = char_top; } if (min_y > char_bottom) { min_y = char_bottom; } if (max_y < char_bottom) { max_y = char_bottom; } charwidth = pCIDFont->GetVertWidth(CID) * fontsize / 1000; } curpos += charwidth; if (charcode == ' ' && (!pCIDFont || pCIDFont->GetCharSize(32) == 1)) { curpos += m_TextState.GetObject()->m_WordSpace; } curpos += m_TextState.GetObject()->m_CharSpace; } if (bVertWriting) { if (pTextAdvanceX) { *pTextAdvanceX = 0; } if (pTextAdvanceY) { *pTextAdvanceY = curpos; } min_x = min_x * fontsize / 1000; max_x = max_x * fontsize / 1000; } else { if (pTextAdvanceX) { *pTextAdvanceX = FXSYS_Mul(curpos, horz_scale); } if (pTextAdvanceY) { *pTextAdvanceY = 0; } min_y = min_y * fontsize / 1000; max_y = max_y * fontsize / 1000; } CFX_AffineMatrix matrix; GetTextMatrix(&matrix); m_Left = min_x; m_Right = max_x; m_Bottom = min_y; m_Top = max_y; matrix.TransformRect(m_Left, m_Right, m_Top, m_Bottom); int textmode = m_TextState.GetObject()->m_TextMode; if (textmode == 1 || textmode == 2 || textmode == 5 || textmode == 6) { FX_FLOAT half_width = m_GraphState.GetObject()->m_LineWidth / 2; m_Left -= half_width; m_Right += half_width; m_Top += half_width; m_Bottom -= half_width; } }
void CPDF_StreamContentParser::AddTextObject(CFX_ByteString* pStrs, FX_FLOAT fInitKerning, FX_FLOAT* pKerning, int nsegs) { CPDF_Font* pFont = m_pCurStates->m_TextState.GetFont(); if (!pFont) { return; } if (fInitKerning != 0) { if (!pFont->IsVertWriting()) { m_pCurStates->m_TextX -= FXSYS_Mul(fInitKerning, m_pCurStates->m_TextState.GetFontSize()) / 1000; } else { m_pCurStates->m_TextY -= FXSYS_Mul(fInitKerning, m_pCurStates->m_TextState.GetFontSize()) / 1000; } } if (nsegs == 0) { return; } int textmode; if (pFont->GetFontType() == PDFFONT_TYPE3) { textmode = 0; } else { textmode = m_pCurStates->m_TextState.GetObject()->m_TextMode; } CPDF_TextObject* pText = new CPDF_TextObject; m_pLastTextObject = pText; SetGraphicStates(pText, TRUE, TRUE, TRUE); if (textmode && textmode != 3 && textmode != 4 && textmode != 7) { FX_FLOAT* pCTM = pText->m_TextState.GetModify()->m_CTM; pCTM[0] = m_pCurStates->m_CTM.a; pCTM[1] = m_pCurStates->m_CTM.c; pCTM[2] = m_pCurStates->m_CTM.b; pCTM[3] = m_pCurStates->m_CTM.d; } pText->SetSegments(pStrs, pKerning, nsegs); pText->m_PosX = m_pCurStates->m_TextX; pText->m_PosY = m_pCurStates->m_TextY + m_pCurStates->m_TextRise; ConvertTextSpace(pText->m_PosX, pText->m_PosY); FX_FLOAT x_advance, y_advance; pText->CalcPositionData(&x_advance, &y_advance, m_pCurStates->m_TextHorzScale, m_Level); m_pCurStates->m_TextX += x_advance; m_pCurStates->m_TextY += y_advance; if (textmode > 3) { CPDF_TextObject* pCopy = new CPDF_TextObject; pCopy->Copy(pText); m_ClipTextList.Add(pCopy); } m_pObjectList->m_ObjectList.AddTail(pText); if (pKerning && pKerning[nsegs - 1] != 0) { if (!pFont->IsVertWriting()) { m_pCurStates->m_TextX -= FXSYS_Mul(pKerning[nsegs - 1], m_pCurStates->m_TextState.GetFontSize()) / 1000; } else { m_pCurStates->m_TextY -= FXSYS_Mul(pKerning[nsegs - 1], m_pCurStates->m_TextState.GetFontSize()) / 1000; } } }
void CFX_PathGenerator::AddArc(FX_FLOAT x, FX_FLOAT y, FX_FLOAT width, FX_FLOAT height, FX_FLOAT start_angle, FX_FLOAT sweep_angle) { #if 0 FX_FIXFLOAT32 sweep = sweep_angle; while (sweep > FIXFLOAT32_PI * 2) { sweep -= FIXFLOAT32_PI * 2; } if (sweep == 0) { return; } m_pPathData->AddPointCount(1); m_pPathData->SetPoint(m_pPathData->GetPointCount() - 1, x + fixmul_8_32_to_8(width, fixcos(start_angle)), y + fixmul_8_32_to_8(height, fixsin(start_angle)), FXPT_MOVETO); FX_FIXFLOAT32 angle1 = 0, angle2; FX_BOOL bDone = FALSE; do { angle2 = angle1 + FIXFLOAT32_PI / 2; if (angle2 >= sweep) { angle2 = sweep; bDone = TRUE; } ArcTo(x, y, width, height, start_angle + angle1, angle2 - angle1); angle1 = angle2; } while (!bDone); #else if (sweep_angle == 0) { return; } static const FX_FLOAT bezier_arc_angle_epsilon = (FX_FLOAT)(0.01f); while (start_angle > FX_PI * 2) { start_angle -= FX_PI * 2; } while (start_angle < 0) { start_angle += FX_PI * 2; } if (sweep_angle >= FX_PI * 2) { sweep_angle = FX_PI * 2; } if (sweep_angle <= -FX_PI * 2) { sweep_angle = -FX_PI * 2; } m_pPathData->AddPointCount(1); m_pPathData->SetPoint(m_pPathData->GetPointCount() - 1, x + FXSYS_Mul(width, FXSYS_cos(start_angle)), y + FXSYS_Mul(height, FXSYS_sin(start_angle)), FXPT_MOVETO); FX_FLOAT total_sweep = 0, local_sweep = 0, prev_sweep = 0; FX_BOOL done = FALSE; do { if (sweep_angle < 0) { prev_sweep = total_sweep; local_sweep = -FX_PI / 2; total_sweep -= FX_PI / 2; if (total_sweep <= sweep_angle + bezier_arc_angle_epsilon) { local_sweep = sweep_angle - prev_sweep; done = TRUE; } } else { prev_sweep = total_sweep; local_sweep = FX_PI / 2; total_sweep += FX_PI / 2; if (total_sweep >= sweep_angle - bezier_arc_angle_epsilon) { local_sweep = sweep_angle - prev_sweep; done = TRUE; } } ArcTo(x, y, width, height, start_angle, local_sweep); start_angle += local_sweep; } while (!done); #endif }
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); }