void CPDF_TextObject::GetCharRect(int index, CFX_FloatRect& rect) const { 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() / 1000; int count = 0; 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) { continue; } if (count != index) { ++count; continue; } FX_FLOAT curpos = i > 0 ? m_pCharPos[i - 1] : 0; FX_RECT char_rect; pFont->GetCharBBox(charcode, char_rect, 0); if (!bVertWriting) { rect.left = curpos + char_rect.left * fontsize; rect.right = curpos + char_rect.right * fontsize; rect.top = char_rect.top * fontsize; rect.bottom = char_rect.bottom * fontsize; } else { FX_WORD CID = pCIDFont->CIDFromCharCode(charcode); short vx, vy; pCIDFont->GetVertOrigin(CID, vx, vy); char_rect.left -= vx; char_rect.right -= vx; char_rect.top -= vy; char_rect.bottom -= vy; rect.left = char_rect.left * fontsize; rect.right = char_rect.right * fontsize; rect.top = curpos + char_rect.top * fontsize; rect.bottom = curpos + char_rect.bottom * fontsize; } return; } }
void CTextPage::ProcessObject(CPDF_PageObject* pObject) { if (pObject->m_Type != PDFPAGE_TEXT) { return; } CPDF_TextObject* pText = (CPDF_TextObject*)pObject; CPDF_Font* pFont = pText->m_TextState.GetFont(); int count = pText->CountItems(); FX_FLOAT* pPosArray = FX_Alloc(FX_FLOAT, count * 2); if (pPosArray) { pText->CalcCharPos(pPosArray); } FX_FLOAT fontsize_h = pText->m_TextState.GetFontSizeH(); FX_FLOAT fontsize_v = pText->m_TextState.GetFontSizeV(); FX_DWORD space_charcode = pFont->CharCodeFromUnicode(' '); FX_FLOAT spacew = 0; if (space_charcode != -1) { spacew = fontsize_h * pFont->GetCharWidthF(space_charcode) / 1000; } if (spacew == 0) { spacew = fontsize_h / 4; } if (pText->m_TextState.GetBaselineAngle() != 0) { int cc = 0; CFX_AffineMatrix matrix; pText->GetTextMatrix(&matrix); for (int i = 0; i < pText->m_nChars; i ++) { FX_DWORD charcode = pText->m_nChars == 1 ? (FX_DWORD)(FX_UINTPTR)pText->m_pCharCodes : pText->m_pCharCodes[i]; if (charcode == (FX_DWORD) - 1) { continue; } FX_RECT char_box; pFont->GetCharBBox(charcode, char_box); FX_FLOAT char_left = pPosArray ? pPosArray[cc * 2] : char_box.left * pText->m_TextState.GetFontSize() / 1000; FX_FLOAT char_right = pPosArray ? pPosArray[cc * 2 + 1] : char_box.right * pText->m_TextState.GetFontSize() / 1000; FX_FLOAT char_top = char_box.top * pText->m_TextState.GetFontSize() / 1000; FX_FLOAT char_bottom = char_box.bottom * pText->m_TextState.GetFontSize() / 1000; cc ++; FX_FLOAT char_origx, char_origy; matrix.Transform(char_left, 0, char_origx, char_origy); matrix.TransformRect(char_left, char_right, char_top, char_bottom); CFX_ByteString str; pFont->AppendChar(str, charcode); InsertTextBox(NULL, char_origy, char_left, char_right, char_top, char_bottom, spacew, fontsize_v, str, pFont); } if (pPosArray) { FX_Free(pPosArray); } return; } FX_FLOAT ratio_h = fontsize_h / pText->m_TextState.GetFontSize(); for (int ii = 0; ii < count * 2; ii ++) { pPosArray[ii] *= ratio_h; } FX_FLOAT baseline = pText->m_PosY; CTextBaseLine* pBaseLine = NULL; FX_FLOAT topy = pText->m_Top; FX_FLOAT bottomy = pText->m_Bottom; FX_FLOAT leftx = pText->m_Left; int cc = 0; CFX_ByteString segment; int space_count = 0; FX_FLOAT last_left = 0, last_right = 0, segment_left = 0, segment_right = 0; for (int i = 0; i < pText->m_nChars; i ++) { FX_DWORD charcode = pText->m_nChars == 1 ? (FX_DWORD)(FX_UINTPTR)pText->m_pCharCodes : pText->m_pCharCodes[i]; if (charcode == (FX_DWORD) - 1) { continue; } FX_FLOAT char_left = pPosArray[cc * 2]; FX_FLOAT char_right = pPosArray[cc * 2 + 1]; cc ++; if (char_left < last_left || (char_left - last_right) > spacew / 2) { pBaseLine = InsertTextBox(pBaseLine, baseline, leftx + segment_left, leftx + segment_right, topy, bottomy, spacew, fontsize_v, segment, pFont); segment_left = char_left; segment = ""; } if (space_count > 1) { pBaseLine = InsertTextBox(pBaseLine, baseline, leftx + segment_left, leftx + segment_right, topy, bottomy, spacew, fontsize_v, segment, pFont); segment = ""; } else if (space_count == 1) { pFont->AppendChar(segment, ' '); } if (segment.GetLength() == 0) { segment_left = char_left; } segment_right = char_right; pFont->AppendChar(segment, charcode); space_count = 0; last_left = char_left; last_right = char_right; } if (segment.GetLength()) pBaseLine = InsertTextBox(pBaseLine, baseline, leftx + segment_left, leftx + segment_right, topy, bottomy, spacew, fontsize_v, segment, pFont); FX_Free(pPosArray); }
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; } }