void CFDE_TxtEdtEngine::GetCaretRect(CFX_RectF& rtCaret, int32_t nPageIndex, int32_t nCaret, FX_BOOL bBefore) { IFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage]; m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0); FX_BOOL bCombText = m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText; int32_t nIndexInpage = nCaret - pPage->GetCharStart(); if (bBefore && bCombText && nIndexInpage > 0) { nIndexInpage--; bBefore = FALSE; } int32_t nBIDILevel = pPage->GetCharRect(nIndexInpage, rtCaret, bCombText); if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) { if ((!FX_IsOdd(nBIDILevel) && !bBefore) || (FX_IsOdd(nBIDILevel) && bBefore)) { rtCaret.Offset(0, rtCaret.height - 1.0f); } if (rtCaret.height == 0 && rtCaret.top > 1.0f) rtCaret.top -= 1.0f; rtCaret.height = 1.0f; } else { if ((!FX_IsOdd(nBIDILevel) && !bBefore) || (FX_IsOdd(nBIDILevel) && bBefore)) { rtCaret.Offset(rtCaret.width - 1.0f, 0); } if (rtCaret.width == 0 && rtCaret.left > 1.0f) rtCaret.left -= 1.0f; rtCaret.width = 1.0f; } m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0); }
int32_t CFDE_TxtEdtPage::LoadPage(const CFX_RectF* pClipBox, IFX_Pause* pPause) { if (m_nRefCount > 0) { m_nRefCount++; return m_nRefCount; } CFDE_TxtEdtBuf* pBuf = m_pEditEngine->GetTextBuf(); const FDE_TXTEDTPARAMS* pParams = m_pEditEngine->GetEditParams(); FX_WCHAR wcAlias = 0; if (pParams->dwMode & FDE_TEXTEDITMODE_Password) { wcAlias = m_pEditEngine->GetAliasChar(); } m_pIter.reset( new CFDE_TxtEdtBufIter(static_cast<CFDE_TxtEdtBuf*>(pBuf), wcAlias)); CFX_TxtBreak* pBreak = m_pEditEngine->GetTextBreak(); pBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); pBreak->ClearBreakPieces(); int32_t nPageLineCount = m_pEditEngine->GetPageLineCount(); int32_t nStartLine = nPageLineCount * m_nPageIndex; int32_t nEndLine = std::min((nStartLine + nPageLineCount - 1), (m_pEditEngine->GetLineCount() - 1)); int32_t nPageStart, nPageEnd, nTemp, nBgnParag, nStartLineInParag, nEndParag, nEndLineInParag; nBgnParag = m_pEditEngine->Line2Parag(0, 0, nStartLine, nStartLineInParag); m_pBgnParag = static_cast<CFDE_TxtEdtParag*>(m_pEditEngine->GetParag(nBgnParag)); m_pBgnParag->LoadParag(); m_pBgnParag->GetLineRange(nStartLine - nStartLineInParag, nPageStart, nTemp); nEndParag = m_pEditEngine->Line2Parag(nBgnParag, nStartLineInParag, nEndLine, nEndLineInParag); m_pEndParag = static_cast<CFDE_TxtEdtParag*>(m_pEditEngine->GetParag(nEndParag)); m_pEndParag->LoadParag(); m_pEndParag->GetLineRange(nEndLine - nEndLineInParag, nPageEnd, nTemp); nPageEnd += (nTemp - 1); FX_BOOL bVertial = pParams->dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical; FX_BOOL bLineReserve = pParams->dwLayoutStyles & FDE_TEXTEDITLAYOUT_LineReserve; FX_FLOAT fLineStart = bVertial ? (bLineReserve ? (pParams->fPlateWidth - pParams->fLineSpace) : 0.0f) : 0.0f; FX_FLOAT fLineStep = (bVertial && bLineReserve) ? (-pParams->fLineSpace) : pParams->fLineSpace; FX_FLOAT fLinePos = fLineStart; if (!m_pTextSet) m_pTextSet = new CFDE_TxtEdtTextSet(this); m_PieceMassArr.RemoveAll(TRUE); uint32_t dwBreakStatus = FX_TXTBREAK_None; int32_t nPieceStart = 0; delete[] m_pCharWidth; m_pCharWidth = new int32_t[nPageEnd - nPageStart + 1]; pBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); pBreak->ClearBreakPieces(); m_nPageStart = nPageStart; m_nCharCount = nPageEnd - nPageStart + 1; FX_BOOL bReload = FALSE; FX_FLOAT fDefCharWidth = 0; std::unique_ptr<IFX_CharIter> pIter(m_pIter->Clone()); pIter->SetAt(nPageStart); m_pIter->SetAt(nPageStart); FX_BOOL bFirstPiece = TRUE; do { if (bReload) { dwBreakStatus = pBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); } else { FX_WCHAR wAppend = pIter->GetChar(); dwBreakStatus = pBreak->AppendChar(wAppend); } if (pIter->GetAt() == nPageEnd && dwBreakStatus < FX_TXTBREAK_LineBreak) { dwBreakStatus = pBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); } if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { int32_t nPieceCount = pBreak->CountBreakPieces(); for (int32_t j = 0; j < nPieceCount; j++) { const CFX_TxtPiece* pPiece = pBreak->GetBreakPiece(j); FDE_TEXTEDITPIECE TxtEdtPiece; FXSYS_memset(&TxtEdtPiece, 0, sizeof(FDE_TEXTEDITPIECE)); TxtEdtPiece.nBidiLevel = pPiece->m_iBidiLevel; TxtEdtPiece.nCount = pPiece->GetLength(); TxtEdtPiece.nStart = nPieceStart; TxtEdtPiece.dwCharStyles = pPiece->m_dwCharStyles; if (FX_IsOdd(pPiece->m_iBidiLevel)) { TxtEdtPiece.dwCharStyles |= FX_TXTCHARSTYLE_OddBidiLevel; } FX_FLOAT fParaBreakWidth = 0.0f; if (pPiece->m_dwStatus > FX_TXTBREAK_PieceBreak) { FX_WCHAR wRtChar = pParams->wLineBreakChar; if (TxtEdtPiece.nCount >= 2) { FX_WCHAR wChar = pBuf->GetCharByIndex( m_nPageStart + TxtEdtPiece.nStart + TxtEdtPiece.nCount - 1); FX_WCHAR wCharPre = pBuf->GetCharByIndex( m_nPageStart + TxtEdtPiece.nStart + TxtEdtPiece.nCount - 2); if (wChar == wRtChar) { fParaBreakWidth += fDefCharWidth; } if (wCharPre == wRtChar) { fParaBreakWidth += fDefCharWidth; } } else if (TxtEdtPiece.nCount >= 1) { FX_WCHAR wChar = pBuf->GetCharByIndex( m_nPageStart + TxtEdtPiece.nStart + TxtEdtPiece.nCount - 1); if (wChar == wRtChar) { fParaBreakWidth += fDefCharWidth; } } } if (pParams->dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) { TxtEdtPiece.rtPiece.left = fLinePos; TxtEdtPiece.rtPiece.top = (FX_FLOAT)pPiece->m_iStartPos / 20000.0f; TxtEdtPiece.rtPiece.width = pParams->fLineSpace; TxtEdtPiece.rtPiece.height = (FX_FLOAT)pPiece->m_iWidth / 20000.0f + fParaBreakWidth; } else { TxtEdtPiece.rtPiece.left = (FX_FLOAT)pPiece->m_iStartPos / 20000.0f; TxtEdtPiece.rtPiece.top = fLinePos; TxtEdtPiece.rtPiece.width = (FX_FLOAT)pPiece->m_iWidth / 20000.0f + fParaBreakWidth; TxtEdtPiece.rtPiece.height = pParams->fLineSpace; } if (bFirstPiece) { m_rtPageContents = TxtEdtPiece.rtPiece; bFirstPiece = FALSE; } else { m_rtPageContents.Union(TxtEdtPiece.rtPiece); } nPieceStart += TxtEdtPiece.nCount; m_PieceMassArr.Add(TxtEdtPiece); for (int32_t k = 0; k < TxtEdtPiece.nCount; k++) { CFX_Char* ptc = pPiece->GetCharPtr(k); m_pCharWidth[TxtEdtPiece.nStart + k] = ptc->m_iCharWidth; } } fLinePos += fLineStep; pBreak->ClearBreakPieces(); } if (pIter->GetAt() == nPageEnd && dwBreakStatus == FX_TXTBREAK_LineBreak) { bReload = TRUE; pIter->Next(TRUE); } } while (pIter->Next(FALSE) && (pIter->GetAt() <= nPageEnd)); if (m_rtPageContents.left != 0) { FX_FLOAT fDelta = 0.0f; if (m_rtPageContents.width < pParams->fPlateWidth) { if (pParams->dwAlignment & FDE_TEXTEDITALIGN_Right) { fDelta = pParams->fPlateWidth - m_rtPageContents.width; } else if (pParams->dwAlignment & FDE_TEXTEDITALIGN_Center) { if ((pParams->dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText) && m_nCharCount > 1) { int32_t nCount = m_nCharCount - 1; int32_t n = (m_pEditEngine->m_nLimit - nCount) / 2; fDelta = (m_rtPageContents.width / nCount) * n; } else { fDelta = (pParams->fPlateWidth - m_rtPageContents.width) / 2; } } } FX_FLOAT fOffset = m_rtPageContents.left - fDelta; int32_t nCount = m_PieceMassArr.GetSize(); for (int32_t i = 0; i < nCount; i++) { FDE_TEXTEDITPIECE* pPiece = m_PieceMassArr.GetPtrAt(i); pPiece->rtPiece.Offset(-fOffset, 0.0f); } m_rtPageContents.Offset(-fOffset, 0.0f); } if (m_pEditEngine->GetEditParams()->dwLayoutStyles & FDE_TEXTEDITLAYOUT_LastLineHeight) { m_rtPageContents.height -= pParams->fLineSpace - pParams->fFontSize; int32_t nCount = m_PieceMassArr.GetSize(); FDE_TEXTEDITPIECE* pPiece = m_PieceMassArr.GetPtrAt(nCount - 1); pPiece->rtPiece.height = pParams->fFontSize; } m_nRefCount = 1; m_bLoaded = TRUE; return 0; }
int32_t CFDE_TxtEdtPage::GetCharIndex(const CFX_PointF& fPoint, FX_BOOL& bBefore) { FX_BOOL bVertical = m_pEditEngine->GetEditParams()->dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical; CFX_PointF ptF = fPoint; NormalizePt2Rect(ptF, m_rtPageContents, kTolerance); int32_t nCount = m_PieceMassArr.GetSize(); CFX_RectF rtLine; int32_t nBgn = 0; int32_t nEnd = 0; FX_BOOL bInLine = FALSE; int32_t i = 0; for (i = 0; i < nCount; i++) { const FDE_TEXTEDITPIECE* pPiece = m_PieceMassArr.GetPtrAt(i); if (!bInLine && (bVertical ? (pPiece->rtPiece.left <= ptF.x && pPiece->rtPiece.right() > ptF.x) : (pPiece->rtPiece.top <= ptF.y && pPiece->rtPiece.bottom() > ptF.y))) { nBgn = nEnd = i; rtLine = pPiece->rtPiece; bInLine = TRUE; } else if (bInLine) { if (bVertical ? (!(pPiece->rtPiece.left <= ptF.x && pPiece->rtPiece.right() > ptF.x)) : (pPiece->rtPiece.bottom() <= ptF.y || pPiece->rtPiece.top > ptF.y)) { nEnd = i - 1; break; } else { rtLine.Union(pPiece->rtPiece); } } } NormalizePt2Rect(ptF, rtLine, kTolerance); int32_t nCaret = 0; FDE_TEXTEDITPIECE* pPiece = nullptr; for (i = nBgn; i <= nEnd; i++) { pPiece = m_PieceMassArr.GetPtrAt(i); nCaret = m_nPageStart + pPiece->nStart; if (pPiece->rtPiece.Contains(ptF)) { CFX_RectFArray rectArr; m_pTextSet->GetCharRects(pPiece, rectArr, FALSE); int32_t nRtCount = rectArr.GetSize(); for (int32_t j = 0; j < nRtCount; j++) { if (rectArr[j].Contains(ptF)) { nCaret = m_nPageStart + pPiece->nStart + j; if (nCaret >= m_pEditEngine->GetTextBufLength()) { bBefore = TRUE; return m_pEditEngine->GetTextBufLength(); } FX_WCHAR wChar = m_pEditEngine->GetTextBuf()->GetCharByIndex(nCaret); if (wChar == L'\n' || wChar == L'\r') { if (wChar == L'\n') { if (m_pEditEngine->GetTextBuf()->GetCharByIndex(nCaret - 1) == L'\r') { nCaret--; } } bBefore = TRUE; return nCaret; } if (bVertical ? (ptF.y > ((rectArr[j].top + rectArr[j].bottom()) / 2)) : (ptF.x > ((rectArr[j].left + rectArr[j].right()) / 2))) { bBefore = FX_IsOdd(pPiece->nBidiLevel); } else { bBefore = !FX_IsOdd(pPiece->nBidiLevel); } return nCaret; } } } } bBefore = TRUE; return nCaret; }
FX_BOOL CFDE_TextOut::RetriecePieces(uint32_t dwBreakStatus, int32_t& iStartChar, int32_t& iPieceWidths, FX_BOOL bReload, const CFX_RectF& rect) { FX_BOOL bSingleLine = !!(m_dwStyles & FDE_TTOSTYLE_SingleLine); FX_BOOL bLineWrap = !!(m_dwStyles & FDE_TTOSTYLE_LineWrap); FX_BOOL bVertical = !!(m_dwStyles & FDE_TTOSTYLE_VerticalLayout); FX_FLOAT fLineStep = (m_fLineSpace > m_fFontSize) ? m_fLineSpace : m_fFontSize; if (bVertical) { fLineStep = -fLineStep; } CFX_Char* pTC = nullptr; FX_BOOL bNeedReload = FALSE; FX_FLOAT fLineWidth = bVertical ? rect.Height() : rect.Width(); int32_t iLineWidth = FXSYS_round(fLineWidth * 20000.0f); int32_t iCount = m_pTxtBreak->CountBreakPieces(); for (int32_t i = 0; i < iCount; i++) { const CFX_TxtPiece* pPiece = m_pTxtBreak->GetBreakPiece(i); int32_t iPieceChars = pPiece->GetLength(); int32_t iChar = iStartChar; int32_t iWidth = 0; int32_t j = 0; for (; j < iPieceChars; j++) { pTC = pPiece->GetCharPtr(j); int32_t iCurCharWidth = pTC->m_iCharWidth > 0 ? pTC->m_iCharWidth : 0; if (bSingleLine || !bLineWrap) { if (iLineWidth - iPieceWidths - iWidth < iCurCharWidth) { bNeedReload = TRUE; break; } } iWidth += iCurCharWidth; m_CharWidths[iChar++] = iCurCharWidth; } if (j == 0 && !bReload) { CFDE_TTOLine* pLine = m_ttoLines.GetPtrAt(m_iCurLine); pLine->m_bNewReload = TRUE; } else if (j > 0) { CFX_RectF rtPiece; if (bVertical) { rtPiece.left = m_fLinePos; rtPiece.top = rect.top + (FX_FLOAT)pPiece->m_iStartPos / 20000.0f; rtPiece.width = fLineStep; rtPiece.height = iWidth / 20000.0f; } else { rtPiece.left = rect.left + (FX_FLOAT)pPiece->m_iStartPos / 20000.0f; rtPiece.top = m_fLinePos; rtPiece.width = iWidth / 20000.0f; rtPiece.height = fLineStep; } FDE_TTOPIECE ttoPiece; ttoPiece.iStartChar = iStartChar; ttoPiece.iChars = j; ttoPiece.rtPiece = rtPiece; ttoPiece.dwCharStyles = pPiece->m_dwCharStyles; if (FX_IsOdd(pPiece->m_iBidiLevel)) { ttoPiece.dwCharStyles |= FX_TXTCHARSTYLE_OddBidiLevel; } AppendPiece(ttoPiece, bNeedReload, (bReload && i == iCount - 1)); } iStartChar += iPieceChars; iPieceWidths += iWidth; } m_pTxtBreak->ClearBreakPieces(); FX_BOOL bRet = bSingleLine || bLineWrap || (!bLineWrap && bNeedReload) || dwBreakStatus == FX_TXTBREAK_ParagraphBreak; return bRet; }