| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
| 6 | |
| 7 #include "xfa/src/fde/tto/fde_textout.h" | |
| 8 | |
| 9 #include <algorithm> | |
| 10 | |
| 11 #include "core/include/fxcrt/fx_coordinates.h" | |
| 12 #include "core/include/fxcrt/fx_system.h" | |
| 13 #include "xfa/src/fde/fde_brush.h" | |
| 14 #include "xfa/src/fde/fde_pen.h" | |
| 15 #include "xfa/src/fde/fde_renderdevice.h" | |
| 16 #include "xfa/src/fgas/crt/fgas_memory.h" | |
| 17 #include "xfa/src/fgas/crt/fgas_utils.h" | |
| 18 #include "xfa/src/fgas/layout/fgas_textbreak.h" | |
| 19 | |
| 20 namespace { | |
| 21 | |
| 22 struct FDE_TTOPIECE { | |
| 23 public: | |
| 24 int32_t iStartChar; | |
| 25 int32_t iChars; | |
| 26 FX_DWORD dwCharStyles; | |
| 27 CFX_RectF rtPiece; | |
| 28 }; | |
| 29 typedef FDE_TTOPIECE* FDE_LPTTOPIECE; | |
| 30 typedef CFX_MassArrayTemplate<FDE_TTOPIECE> CFDE_TTOPieceArray; | |
| 31 | |
| 32 class CFDE_TTOLine : public CFX_Target { | |
| 33 public: | |
| 34 CFDE_TTOLine(); | |
| 35 CFDE_TTOLine(const CFDE_TTOLine& ttoLine); | |
| 36 ~CFDE_TTOLine(); | |
| 37 int32_t AddPiece(int32_t index, const FDE_TTOPIECE& ttoPiece); | |
| 38 int32_t GetSize() const; | |
| 39 FDE_LPTTOPIECE GetPtrAt(int32_t index); | |
| 40 void RemoveLast(int32_t iCount); | |
| 41 void RemoveAll(FX_BOOL bLeaveMemory); | |
| 42 FX_BOOL m_bNewReload; | |
| 43 CFDE_TTOPieceArray m_pieces; | |
| 44 | |
| 45 protected: | |
| 46 int32_t m_iPieceCount; | |
| 47 }; | |
| 48 typedef CFX_ObjectMassArrayTemplate<CFDE_TTOLine> CFDE_TTOLineArray; | |
| 49 | |
| 50 class CFDE_TextOut : public IFDE_TextOut, public CFX_Target { | |
| 51 public: | |
| 52 CFDE_TextOut(); | |
| 53 ~CFDE_TextOut(); | |
| 54 virtual void Release() { delete this; } | |
| 55 virtual void SetFont(IFX_Font* pFont); | |
| 56 virtual void SetFontSize(FX_FLOAT fFontSize); | |
| 57 virtual void SetTextColor(FX_ARGB color); | |
| 58 virtual void SetStyles(FX_DWORD dwStyles); | |
| 59 virtual void SetTabWidth(FX_FLOAT fTabWidth); | |
| 60 virtual void SetEllipsisString(const CFX_WideString& wsEllipsis); | |
| 61 virtual void SetParagraphBreakChar(FX_WCHAR wch); | |
| 62 virtual void SetAlignment(int32_t iAlignment); | |
| 63 virtual void SetLineSpace(FX_FLOAT fLineSpace); | |
| 64 virtual void SetDIBitmap(CFX_DIBitmap* pDIB); | |
| 65 virtual void SetRenderDevice(CFX_RenderDevice* pDevice); | |
| 66 virtual void SetClipRect(const CFX_Rect& rtClip); | |
| 67 virtual void SetClipRect(const CFX_RectF& rtClip); | |
| 68 virtual void SetMatrix(const CFX_Matrix& matrix); | |
| 69 virtual void SetLineBreakTolerance(FX_FLOAT fTolerance); | |
| 70 virtual void CalcSize(const FX_WCHAR* pwsStr, | |
| 71 int32_t iLength, | |
| 72 CFX_Size& size); | |
| 73 virtual void CalcSize(const FX_WCHAR* pwsStr, | |
| 74 int32_t iLength, | |
| 75 CFX_SizeF& size); | |
| 76 virtual void CalcSize(const FX_WCHAR* pwsStr, | |
| 77 int32_t iLength, | |
| 78 CFX_Rect& rect); | |
| 79 virtual void CalcSize(const FX_WCHAR* pwsStr, | |
| 80 int32_t iLength, | |
| 81 CFX_RectF& rect); | |
| 82 | |
| 83 virtual void DrawText(const FX_WCHAR* pwsStr, | |
| 84 int32_t iLength, | |
| 85 int32_t x, | |
| 86 int32_t y); | |
| 87 virtual void DrawText(const FX_WCHAR* pwsStr, | |
| 88 int32_t iLength, | |
| 89 FX_FLOAT x, | |
| 90 FX_FLOAT y); | |
| 91 virtual void DrawText(const FX_WCHAR* pwsStr, | |
| 92 int32_t iLength, | |
| 93 const CFX_Rect& rect); | |
| 94 virtual void DrawText(const FX_WCHAR* pwsStr, | |
| 95 int32_t iLength, | |
| 96 const CFX_RectF& rect); | |
| 97 | |
| 98 virtual void SetLogicClipRect(const CFX_RectF& rtClip); | |
| 99 virtual void CalcLogicSize(const FX_WCHAR* pwsStr, | |
| 100 int32_t iLength, | |
| 101 CFX_SizeF& size); | |
| 102 virtual void CalcLogicSize(const FX_WCHAR* pwsStr, | |
| 103 int32_t iLength, | |
| 104 CFX_RectF& rect); | |
| 105 virtual void DrawLogicText(const FX_WCHAR* pwsStr, | |
| 106 int32_t iLength, | |
| 107 FX_FLOAT x, | |
| 108 FX_FLOAT y); | |
| 109 virtual void DrawLogicText(const FX_WCHAR* pwsStr, | |
| 110 int32_t iLength, | |
| 111 const CFX_RectF& rect); | |
| 112 virtual int32_t GetTotalLines(); | |
| 113 | |
| 114 protected: | |
| 115 void CalcTextSize(const FX_WCHAR* pwsStr, int32_t iLength, CFX_RectF& rect); | |
| 116 FX_BOOL RetrieveLineWidth(FX_DWORD dwBreakStatus, | |
| 117 FX_FLOAT& fStartPos, | |
| 118 FX_FLOAT& fWidth, | |
| 119 FX_FLOAT& fHeight); | |
| 120 void SetLineWidth(CFX_RectF& rect); | |
| 121 void DrawText(const FX_WCHAR* pwsStr, | |
| 122 int32_t iLength, | |
| 123 const CFX_RectF& rect, | |
| 124 const CFX_RectF& rtClip); | |
| 125 void LoadText(const FX_WCHAR* pwsStr, int32_t iLength, const CFX_RectF& rect); | |
| 126 void LoadEllipsis(); | |
| 127 void ExpandBuffer(int32_t iSize, int32_t iType); | |
| 128 void RetrieveEllPieces(int32_t*& pCharWidths); | |
| 129 | |
| 130 void Reload(const CFX_RectF& rect); | |
| 131 void ReloadLinePiece(CFDE_TTOLine* pLine, const CFX_RectF& rect); | |
| 132 FX_BOOL RetriecePieces(FX_DWORD dwBreakStatus, | |
| 133 int32_t& iStartChar, | |
| 134 int32_t& iPieceWidths, | |
| 135 FX_BOOL bReload, | |
| 136 const CFX_RectF& rect); | |
| 137 void AppendPiece(const FDE_TTOPIECE& ttoPiece, | |
| 138 FX_BOOL bNeedReload, | |
| 139 FX_BOOL bEnd); | |
| 140 void ReplaceWidthEllipsis(); | |
| 141 void DoAlignment(const CFX_RectF& rect); | |
| 142 void OnDraw(const CFX_RectF& rtClip); | |
| 143 int32_t GetDisplayPos(FDE_LPTTOPIECE pPiece); | |
| 144 int32_t GetCharRects(FDE_LPTTOPIECE pPiece); | |
| 145 | |
| 146 void ToTextRun(const FDE_LPTTOPIECE pPiece, FX_TXTRUN& tr); | |
| 147 void DrawLine(const FDE_LPTTOPIECE pPiece, IFDE_Pen*& pPen); | |
| 148 | |
| 149 IFX_TxtBreak* m_pTxtBreak; | |
| 150 IFX_Font* m_pFont; | |
| 151 FX_FLOAT m_fFontSize; | |
| 152 FX_FLOAT m_fLineSpace; | |
| 153 FX_FLOAT m_fLinePos; | |
| 154 FX_FLOAT m_fTolerance; | |
| 155 int32_t m_iAlignment; | |
| 156 int32_t m_iTxtBkAlignment; | |
| 157 int32_t* m_pCharWidths; | |
| 158 int32_t m_iChars; | |
| 159 int32_t* m_pEllCharWidths; | |
| 160 int32_t m_iEllChars; | |
| 161 FX_WCHAR m_wParagraphBkChar; | |
| 162 FX_ARGB m_TxtColor; | |
| 163 FX_DWORD m_dwStyles; | |
| 164 FX_DWORD m_dwTxtBkStyles; | |
| 165 CFX_WideString m_wsEllipsis; | |
| 166 FX_BOOL m_bElliChanged; | |
| 167 int32_t m_iEllipsisWidth; | |
| 168 CFX_WideString m_wsText; | |
| 169 CFX_RectF m_rtClip; | |
| 170 CFX_RectF m_rtLogicClip; | |
| 171 CFX_Matrix m_Matrix; | |
| 172 CFDE_TTOLineArray m_ttoLines; | |
| 173 int32_t m_iCurLine; | |
| 174 int32_t m_iCurPiece; | |
| 175 int32_t m_iTotalLines; | |
| 176 FXTEXT_CHARPOS* m_pCharPos; | |
| 177 int32_t m_iCharPosSize; | |
| 178 IFDE_RenderDevice* m_pRenderDevice; | |
| 179 CFX_Int32Array m_hotKeys; | |
| 180 CFX_RectFArray m_rectArray; | |
| 181 }; | |
| 182 | |
| 183 } // namespace | |
| 184 | |
| 185 IFDE_TextOut* IFDE_TextOut::Create() { | |
| 186 return new CFDE_TextOut; | |
| 187 } | |
| 188 CFDE_TextOut::CFDE_TextOut() | |
| 189 : m_pFont(NULL), | |
| 190 m_fFontSize(12.0f), | |
| 191 m_fLineSpace(m_fFontSize), | |
| 192 m_fLinePos(0.0f), | |
| 193 m_fTolerance(0.0f), | |
| 194 m_iAlignment(0), | |
| 195 m_iTxtBkAlignment(0), | |
| 196 m_pCharWidths(NULL), | |
| 197 m_iChars(0), | |
| 198 m_pEllCharWidths(NULL), | |
| 199 m_iEllChars(0), | |
| 200 m_wParagraphBkChar(L'\n'), | |
| 201 m_TxtColor(0xFF000000), | |
| 202 m_dwStyles(0), | |
| 203 m_dwTxtBkStyles(0), | |
| 204 m_bElliChanged(FALSE), | |
| 205 m_iEllipsisWidth(0), | |
| 206 m_ttoLines(5), | |
| 207 m_iCurLine(0), | |
| 208 m_iCurPiece(0), | |
| 209 m_iTotalLines(0), | |
| 210 m_pCharPos(NULL), | |
| 211 m_iCharPosSize(0), | |
| 212 m_pRenderDevice(NULL) { | |
| 213 m_pTxtBreak = IFX_TxtBreak::Create(FX_TXTBREAKPOLICY_None); | |
| 214 FXSYS_assert(m_pTxtBreak != NULL); | |
| 215 m_Matrix.SetIdentity(); | |
| 216 m_rtClip.Reset(); | |
| 217 m_rtLogicClip.Reset(); | |
| 218 } | |
| 219 CFDE_TextOut::~CFDE_TextOut() { | |
| 220 if (m_pTxtBreak) { | |
| 221 m_pTxtBreak->Release(); | |
| 222 } | |
| 223 FX_Free(m_pCharWidths); | |
| 224 FX_Free(m_pEllCharWidths); | |
| 225 if (m_pRenderDevice) { | |
| 226 m_pRenderDevice->Release(); | |
| 227 } | |
| 228 FX_Free(m_pCharPos); | |
| 229 m_ttoLines.RemoveAll(); | |
| 230 } | |
| 231 void CFDE_TextOut::SetFont(IFX_Font* pFont) { | |
| 232 FXSYS_assert(pFont); | |
| 233 m_pFont = pFont; | |
| 234 m_pTxtBreak->SetFont(pFont); | |
| 235 } | |
| 236 void CFDE_TextOut::SetFontSize(FX_FLOAT fFontSize) { | |
| 237 FXSYS_assert(fFontSize > 0); | |
| 238 m_fFontSize = fFontSize; | |
| 239 m_pTxtBreak->SetFontSize(fFontSize); | |
| 240 } | |
| 241 void CFDE_TextOut::SetTextColor(FX_ARGB color) { | |
| 242 m_TxtColor = color; | |
| 243 } | |
| 244 void CFDE_TextOut::SetStyles(FX_DWORD dwStyles) { | |
| 245 m_dwStyles = dwStyles; | |
| 246 m_dwTxtBkStyles = 0; | |
| 247 if (dwStyles & FDE_TTOSTYLE_SingleLine) { | |
| 248 m_dwTxtBkStyles |= FX_TXTLAYOUTSTYLE_SingleLine; | |
| 249 } | |
| 250 if (dwStyles & FDE_TTOSTYLE_ExpandTab) { | |
| 251 m_dwTxtBkStyles |= FX_TXTLAYOUTSTYLE_ExpandTab; | |
| 252 } | |
| 253 if (dwStyles & FDE_TTOSTYLE_ArabicShapes) { | |
| 254 m_dwTxtBkStyles |= FX_TXTLAYOUTSTYLE_ArabicShapes; | |
| 255 } | |
| 256 if (dwStyles & FDE_TTOSTYLE_RTL) { | |
| 257 m_dwTxtBkStyles |= FX_TXTLAYOUTSTYLE_RTLReadingOrder; | |
| 258 } | |
| 259 if (dwStyles & FDE_TTOSTYLE_ArabicContext) { | |
| 260 m_dwTxtBkStyles |= FX_TXTLAYOUTSTYLE_ArabicContext; | |
| 261 } | |
| 262 if (dwStyles & FDE_TTOSTYLE_VerticalLayout) { | |
| 263 m_dwTxtBkStyles |= | |
| 264 (FX_TXTLAYOUTSTYLE_VerticalChars | FX_TXTLAYOUTSTYLE_VerticalLayout); | |
| 265 } | |
| 266 m_pTxtBreak->SetLayoutStyles(m_dwTxtBkStyles); | |
| 267 } | |
| 268 void CFDE_TextOut::SetTabWidth(FX_FLOAT fTabWidth) { | |
| 269 FXSYS_assert(fTabWidth > 1.0f); | |
| 270 m_pTxtBreak->SetTabWidth(fTabWidth, FALSE); | |
| 271 } | |
| 272 void CFDE_TextOut::SetEllipsisString(const CFX_WideString& wsEllipsis) { | |
| 273 m_bElliChanged = TRUE; | |
| 274 m_wsEllipsis = wsEllipsis; | |
| 275 } | |
| 276 void CFDE_TextOut::SetParagraphBreakChar(FX_WCHAR wch) { | |
| 277 m_wParagraphBkChar = wch; | |
| 278 m_pTxtBreak->SetParagraphBreakChar(wch); | |
| 279 } | |
| 280 void CFDE_TextOut::SetAlignment(int32_t iAlignment) { | |
| 281 m_iAlignment = iAlignment; | |
| 282 switch (m_iAlignment) { | |
| 283 case FDE_TTOALIGNMENT_TopCenter: | |
| 284 case FDE_TTOALIGNMENT_Center: | |
| 285 case FDE_TTOALIGNMENT_BottomCenter: | |
| 286 m_iTxtBkAlignment = FX_TXTLINEALIGNMENT_Center; | |
| 287 break; | |
| 288 case FDE_TTOALIGNMENT_TopRight: | |
| 289 case FDE_TTOALIGNMENT_CenterRight: | |
| 290 case FDE_TTOALIGNMENT_BottomRight: | |
| 291 m_iTxtBkAlignment = FX_TXTLINEALIGNMENT_Right; | |
| 292 break; | |
| 293 default: | |
| 294 m_iTxtBkAlignment = FX_TXTLINEALIGNMENT_Left; | |
| 295 break; | |
| 296 } | |
| 297 m_pTxtBreak->SetAlignment(m_iTxtBkAlignment); | |
| 298 } | |
| 299 void CFDE_TextOut::SetLineSpace(FX_FLOAT fLineSpace) { | |
| 300 FXSYS_assert(fLineSpace > 1.0f); | |
| 301 m_fLineSpace = fLineSpace; | |
| 302 } | |
| 303 void CFDE_TextOut::SetDIBitmap(CFX_DIBitmap* pDIB) { | |
| 304 FXSYS_assert(pDIB != NULL); | |
| 305 if (m_pRenderDevice != NULL) { | |
| 306 m_pRenderDevice->Release(); | |
| 307 } | |
| 308 m_pRenderDevice = IFDE_RenderDevice::Create(pDIB); | |
| 309 } | |
| 310 void CFDE_TextOut::SetRenderDevice(CFX_RenderDevice* pDevice) { | |
| 311 FXSYS_assert(pDevice != NULL); | |
| 312 if (m_pRenderDevice != NULL) { | |
| 313 m_pRenderDevice->Release(); | |
| 314 } | |
| 315 m_pRenderDevice = IFDE_RenderDevice::Create(pDevice); | |
| 316 } | |
| 317 void CFDE_TextOut::SetClipRect(const CFX_Rect& rtClip) { | |
| 318 m_rtClip.Set((FX_FLOAT)rtClip.left, (FX_FLOAT)rtClip.top, | |
| 319 (FX_FLOAT)rtClip.Width(), (FX_FLOAT)rtClip.Height()); | |
| 320 } | |
| 321 void CFDE_TextOut::SetClipRect(const CFX_RectF& rtClip) { | |
| 322 m_rtClip = rtClip; | |
| 323 } | |
| 324 void CFDE_TextOut::SetLogicClipRect(const CFX_RectF& rtClip) { | |
| 325 m_rtLogicClip = rtClip; | |
| 326 } | |
| 327 void CFDE_TextOut::SetMatrix(const CFX_Matrix& matrix) { | |
| 328 m_Matrix = matrix; | |
| 329 } | |
| 330 void CFDE_TextOut::SetLineBreakTolerance(FX_FLOAT fTolerance) { | |
| 331 m_fTolerance = fTolerance; | |
| 332 m_pTxtBreak->SetLineBreakTolerance(m_fTolerance); | |
| 333 } | |
| 334 int32_t CFDE_TextOut::GetTotalLines() { | |
| 335 return m_iTotalLines; | |
| 336 } | |
| 337 void CFDE_TextOut::CalcSize(const FX_WCHAR* pwsStr, | |
| 338 int32_t iLength, | |
| 339 CFX_Size& size) { | |
| 340 CFX_RectF rtText; | |
| 341 rtText.Set(0.0f, 0.0f, (FX_FLOAT)size.x, (FX_FLOAT)size.y); | |
| 342 CalcSize(pwsStr, iLength, rtText); | |
| 343 size.x = (int32_t)rtText.Width(); | |
| 344 size.y = (int32_t)rtText.Height(); | |
| 345 } | |
| 346 void CFDE_TextOut::CalcSize(const FX_WCHAR* pwsStr, | |
| 347 int32_t iLength, | |
| 348 CFX_SizeF& size) { | |
| 349 CFX_RectF rtText; | |
| 350 rtText.Set(0.0f, 0.0f, size.x, size.y); | |
| 351 CalcSize(pwsStr, iLength, rtText); | |
| 352 size.x = rtText.Width(); | |
| 353 size.y = rtText.Height(); | |
| 354 } | |
| 355 void CFDE_TextOut::CalcSize(const FX_WCHAR* pwsStr, | |
| 356 int32_t iLength, | |
| 357 CFX_Rect& rect) { | |
| 358 CFX_RectF rtText; | |
| 359 rtText.Set((FX_FLOAT)rect.left, (FX_FLOAT)rect.top, (FX_FLOAT)rect.Width(), | |
| 360 (FX_FLOAT)rect.Height()); | |
| 361 CalcSize(pwsStr, iLength, rtText); | |
| 362 rect.Set((int32_t)rtText.left, (int32_t)rtText.top, (int32_t)rtText.Width(), | |
| 363 (int32_t)rtText.Height()); | |
| 364 } | |
| 365 void CFDE_TextOut::CalcSize(const FX_WCHAR* pwsStr, | |
| 366 int32_t iLength, | |
| 367 CFX_RectF& rect) { | |
| 368 if (pwsStr == NULL || iLength < 1) { | |
| 369 rect.width = 0.0f; | |
| 370 rect.height = 0.0f; | |
| 371 } else { | |
| 372 CFX_Matrix rm; | |
| 373 rm.SetReverse(m_Matrix); | |
| 374 rm.TransformRect(rect); | |
| 375 CalcTextSize(pwsStr, iLength, rect); | |
| 376 m_Matrix.TransformRect(rect); | |
| 377 } | |
| 378 } | |
| 379 void CFDE_TextOut::CalcLogicSize(const FX_WCHAR* pwsStr, | |
| 380 int32_t iLength, | |
| 381 CFX_SizeF& size) { | |
| 382 CFX_RectF rtText; | |
| 383 rtText.Set(0.0f, 0.0f, size.x, size.y); | |
| 384 CalcLogicSize(pwsStr, iLength, rtText); | |
| 385 size.x = rtText.Width(); | |
| 386 size.y = rtText.Height(); | |
| 387 } | |
| 388 void CFDE_TextOut::CalcLogicSize(const FX_WCHAR* pwsStr, | |
| 389 int32_t iLength, | |
| 390 CFX_RectF& rect) { | |
| 391 if (pwsStr == NULL || iLength < 1) { | |
| 392 rect.width = 0.0f; | |
| 393 rect.height = 0.0f; | |
| 394 } else { | |
| 395 CalcTextSize(pwsStr, iLength, rect); | |
| 396 } | |
| 397 } | |
| 398 void CFDE_TextOut::CalcTextSize(const FX_WCHAR* pwsStr, | |
| 399 int32_t iLength, | |
| 400 CFX_RectF& rect) { | |
| 401 FXSYS_assert(m_pFont != NULL && m_fFontSize >= 1.0f); | |
| 402 SetLineWidth(rect); | |
| 403 m_iTotalLines = 0; | |
| 404 const FX_WCHAR* pStr = pwsStr; | |
| 405 FX_BOOL bHotKey = !!(m_dwStyles & FDE_TTOSTYLE_HotKey); | |
| 406 FX_BOOL bVertical = !!(m_dwStyles & FDE_TTOSTYLE_VerticalLayout); | |
| 407 FX_FLOAT fWidth = 0.0f; | |
| 408 FX_FLOAT fHeight = 0.0f; | |
| 409 FX_FLOAT fStartPos = bVertical ? rect.bottom() : rect.right(); | |
| 410 FX_DWORD dwBreakStatus = 0; | |
| 411 FX_WCHAR wPreChar = 0; | |
| 412 FX_WCHAR wch; | |
| 413 FX_WCHAR wBreak = 0; | |
| 414 while (iLength-- > 0) { | |
| 415 wch = *pStr++; | |
| 416 if (wBreak == 0 && (wch == L'\n' || wch == L'\r')) { | |
| 417 wBreak = wch; | |
| 418 m_pTxtBreak->SetParagraphBreakChar(wch); | |
| 419 } | |
| 420 if (bHotKey && wch == L'&' && wPreChar != L'&') { | |
| 421 wPreChar = wch; | |
| 422 continue; | |
| 423 } | |
| 424 dwBreakStatus = m_pTxtBreak->AppendChar(wch); | |
| 425 if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { | |
| 426 RetrieveLineWidth(dwBreakStatus, fStartPos, fWidth, fHeight); | |
| 427 } | |
| 428 wPreChar = 0; | |
| 429 } | |
| 430 dwBreakStatus = m_pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); | |
| 431 if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { | |
| 432 RetrieveLineWidth(dwBreakStatus, fStartPos, fWidth, fHeight); | |
| 433 } | |
| 434 m_pTxtBreak->Reset(); | |
| 435 FX_FLOAT fInc = rect.Height() - fHeight; | |
| 436 if (bVertical) { | |
| 437 fInc = rect.Width() - fHeight; | |
| 438 } | |
| 439 if (m_iAlignment >= FDE_TTOALIGNMENT_CenterLeft && | |
| 440 m_iAlignment < FDE_TTOALIGNMENT_BottomLeft) { | |
| 441 fInc /= 2.0f; | |
| 442 } else if (m_iAlignment < FDE_TTOALIGNMENT_CenterLeft) { | |
| 443 fInc = 0.0f; | |
| 444 } | |
| 445 if (bVertical) { | |
| 446 rect.top += fStartPos; | |
| 447 rect.left += fInc; | |
| 448 rect.width = fHeight; | |
| 449 rect.height = std::min(fWidth, rect.Height()); | |
| 450 } else { | |
| 451 rect.left += fStartPos; | |
| 452 rect.top += fInc; | |
| 453 rect.width = std::min(fWidth, rect.Width()); | |
| 454 rect.height = fHeight; | |
| 455 if (m_dwStyles & FDE_TTOSTYLE_LastLineHeight) { | |
| 456 rect.height -= m_fLineSpace - m_fFontSize; | |
| 457 } | |
| 458 } | |
| 459 } | |
| 460 void CFDE_TextOut::SetLineWidth(CFX_RectF& rect) { | |
| 461 if ((m_dwStyles & FDE_TTOSTYLE_SingleLine) == 0) { | |
| 462 FX_FLOAT fLineWidth = 0.0f; | |
| 463 if (m_dwStyles & FDE_TTOSTYLE_VerticalLayout) { | |
| 464 if (rect.Height() < 1.0f) { | |
| 465 rect.height = m_fFontSize * 1000.0f; | |
| 466 } | |
| 467 fLineWidth = rect.Height(); | |
| 468 } else { | |
| 469 if (rect.Width() < 1.0f) { | |
| 470 rect.width = m_fFontSize * 1000.0f; | |
| 471 } | |
| 472 fLineWidth = rect.Width(); | |
| 473 } | |
| 474 m_pTxtBreak->SetLineWidth(fLineWidth); | |
| 475 } | |
| 476 } | |
| 477 FX_BOOL CFDE_TextOut::RetrieveLineWidth(FX_DWORD dwBreakStatus, | |
| 478 FX_FLOAT& fStartPos, | |
| 479 FX_FLOAT& fWidth, | |
| 480 FX_FLOAT& fHeight) { | |
| 481 if (dwBreakStatus <= FX_TXTBREAK_PieceBreak) { | |
| 482 return FALSE; | |
| 483 } | |
| 484 FX_FLOAT fLineStep = | |
| 485 (m_fLineSpace > m_fFontSize) ? m_fLineSpace : m_fFontSize; | |
| 486 FX_BOOL bLineWrap = !!(m_dwStyles & FDE_TTOSTYLE_LineWrap); | |
| 487 FX_FLOAT fLineWidth = 0.0f; | |
| 488 int32_t iCount = m_pTxtBreak->CountBreakPieces(); | |
| 489 for (int32_t i = 0; i < iCount; i++) { | |
| 490 const CFX_TxtPiece* pPiece = m_pTxtBreak->GetBreakPiece(i); | |
| 491 fLineWidth += (FX_FLOAT)pPiece->m_iWidth / 20000.0f; | |
| 492 fStartPos = std::min(fStartPos, (FX_FLOAT)pPiece->m_iStartPos / 20000.0f); | |
| 493 } | |
| 494 m_pTxtBreak->ClearBreakPieces(); | |
| 495 if (dwBreakStatus == FX_TXTBREAK_ParagraphBreak) { | |
| 496 m_pTxtBreak->Reset(); | |
| 497 } | |
| 498 if (!bLineWrap && dwBreakStatus == FX_TXTBREAK_LineBreak) { | |
| 499 fWidth += fLineWidth; | |
| 500 } else { | |
| 501 fWidth = std::max(fWidth, fLineWidth); | |
| 502 fHeight += fLineStep; | |
| 503 } | |
| 504 m_iTotalLines++; | |
| 505 return TRUE; | |
| 506 } | |
| 507 void CFDE_TextOut::DrawText(const FX_WCHAR* pwsStr, | |
| 508 int32_t iLength, | |
| 509 int32_t x, | |
| 510 int32_t y) { | |
| 511 CFX_RectF rtText; | |
| 512 rtText.Set((FX_FLOAT)x, (FX_FLOAT)y, m_fFontSize * 1000.0f, | |
| 513 m_fFontSize * 1000.0f); | |
| 514 DrawText(pwsStr, iLength, rtText); | |
| 515 } | |
| 516 void CFDE_TextOut::DrawText(const FX_WCHAR* pwsStr, | |
| 517 int32_t iLength, | |
| 518 FX_FLOAT x, | |
| 519 FX_FLOAT y) { | |
| 520 CFX_RectF rtText; | |
| 521 rtText.Set(x, y, m_fFontSize * 1000.0f, m_fFontSize * 1000.0f); | |
| 522 DrawText(pwsStr, iLength, rtText); | |
| 523 } | |
| 524 void CFDE_TextOut::DrawText(const FX_WCHAR* pwsStr, | |
| 525 int32_t iLength, | |
| 526 const CFX_Rect& rect) { | |
| 527 CFX_RectF rtText; | |
| 528 rtText.Set((FX_FLOAT)rect.left, (FX_FLOAT)rect.top, (FX_FLOAT)rect.width, | |
| 529 (FX_FLOAT)rect.height); | |
| 530 DrawText(pwsStr, iLength, rtText); | |
| 531 } | |
| 532 void CFDE_TextOut::DrawText(const FX_WCHAR* pwsStr, | |
| 533 int32_t iLength, | |
| 534 const CFX_RectF& rect) { | |
| 535 CFX_RectF rtText; | |
| 536 rtText.Set(rect.left, rect.top, rect.width, rect.height); | |
| 537 CFX_Matrix rm; | |
| 538 rm.SetReverse(m_Matrix); | |
| 539 rm.TransformRect(rtText); | |
| 540 DrawText(pwsStr, iLength, rtText, m_rtClip); | |
| 541 } | |
| 542 void CFDE_TextOut::DrawLogicText(const FX_WCHAR* pwsStr, | |
| 543 int32_t iLength, | |
| 544 FX_FLOAT x, | |
| 545 FX_FLOAT y) { | |
| 546 CFX_RectF rtText; | |
| 547 rtText.Set(x, y, m_fFontSize * 1000.0f, m_fFontSize * 1000.0f); | |
| 548 DrawLogicText(pwsStr, iLength, rtText); | |
| 549 } | |
| 550 void CFDE_TextOut::DrawLogicText(const FX_WCHAR* pwsStr, | |
| 551 int32_t iLength, | |
| 552 const CFX_RectF& rect) { | |
| 553 CFX_RectF rtClip; | |
| 554 rtClip.Set(m_rtLogicClip.left, m_rtLogicClip.top, m_rtLogicClip.width, | |
| 555 m_rtLogicClip.height); | |
| 556 m_Matrix.TransformRect(rtClip); | |
| 557 DrawText(pwsStr, iLength, rect, rtClip); | |
| 558 } | |
| 559 void CFDE_TextOut::DrawText(const FX_WCHAR* pwsStr, | |
| 560 int32_t iLength, | |
| 561 const CFX_RectF& rect, | |
| 562 const CFX_RectF& rtClip) { | |
| 563 FXSYS_assert(m_pFont != NULL && m_fFontSize >= 1.0f); | |
| 564 if (pwsStr == NULL || iLength < 1) { | |
| 565 return; | |
| 566 } | |
| 567 if (rect.width < m_fFontSize || rect.height < m_fFontSize) { | |
| 568 return; | |
| 569 } | |
| 570 FX_FLOAT fLineWidth = rect.width; | |
| 571 if (m_dwStyles & FDE_TTOSTYLE_VerticalLayout) { | |
| 572 fLineWidth = rect.height; | |
| 573 } | |
| 574 m_pTxtBreak->SetLineWidth(fLineWidth); | |
| 575 m_ttoLines.RemoveAll(TRUE); | |
| 576 m_wsText.Empty(); | |
| 577 LoadText(pwsStr, iLength, rect); | |
| 578 if (m_dwStyles & FDE_TTOSTYLE_Ellipsis) { | |
| 579 ReplaceWidthEllipsis(); | |
| 580 } | |
| 581 Reload(rect); | |
| 582 DoAlignment(rect); | |
| 583 OnDraw(rtClip); | |
| 584 } | |
| 585 void CFDE_TextOut::ExpandBuffer(int32_t iSize, int32_t iType) { | |
| 586 switch (iType) { | |
| 587 case 0: | |
| 588 if (!m_pCharWidths) { | |
| 589 m_pCharWidths = FX_Alloc(int32_t, iSize); | |
| 590 m_iChars = iSize; | |
| 591 } else if (m_iChars < iSize) { | |
| 592 m_pCharWidths = FX_Realloc(int32_t, m_pCharWidths, iSize); | |
| 593 m_iChars = iSize; | |
| 594 } | |
| 595 FXSYS_memset(m_pCharWidths, 0, iSize * sizeof(int32_t)); | |
| 596 break; | |
| 597 case 1: | |
| 598 if (!m_pEllCharWidths) { | |
| 599 m_pEllCharWidths = FX_Alloc(int32_t, iSize); | |
| 600 m_iEllChars = iSize; | |
| 601 } else if (m_iEllChars < iSize) { | |
| 602 m_pEllCharWidths = FX_Realloc(int32_t, m_pEllCharWidths, iSize); | |
| 603 m_iEllChars = iSize; | |
| 604 } | |
| 605 FXSYS_memset(m_pEllCharWidths, 0, iSize * sizeof(int32_t)); | |
| 606 break; | |
| 607 case 2: | |
| 608 if (m_pCharPos == NULL) { | |
| 609 m_pCharPos = FX_Alloc(FXTEXT_CHARPOS, iSize); | |
| 610 m_iCharPosSize = iSize; | |
| 611 } else if (m_iCharPosSize < iSize) { | |
| 612 m_pCharPos = FX_Realloc(FXTEXT_CHARPOS, m_pCharPos, iSize); | |
| 613 m_iCharPosSize = iSize; | |
| 614 } | |
| 615 break; | |
| 616 } | |
| 617 } | |
| 618 void CFDE_TextOut::LoadEllipsis() { | |
| 619 if (!m_bElliChanged) { | |
| 620 return; | |
| 621 } | |
| 622 m_bElliChanged = FALSE; | |
| 623 m_iEllipsisWidth = 0; | |
| 624 int32_t iLength = m_wsEllipsis.GetLength(); | |
| 625 if (iLength < 1) { | |
| 626 return; | |
| 627 } | |
| 628 ExpandBuffer(iLength, 1); | |
| 629 const FX_WCHAR* pStr = (const FX_WCHAR*)m_wsEllipsis; | |
| 630 int32_t* pCharWidths = m_pEllCharWidths; | |
| 631 FX_DWORD dwBreakStatus; | |
| 632 FX_WCHAR wch; | |
| 633 while (iLength-- > 0) { | |
| 634 wch = *pStr++; | |
| 635 dwBreakStatus = m_pTxtBreak->AppendChar(wch); | |
| 636 if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { | |
| 637 RetrieveEllPieces(pCharWidths); | |
| 638 } | |
| 639 } | |
| 640 dwBreakStatus = m_pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); | |
| 641 if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { | |
| 642 RetrieveEllPieces(pCharWidths); | |
| 643 } | |
| 644 m_pTxtBreak->Reset(); | |
| 645 } | |
| 646 void CFDE_TextOut::RetrieveEllPieces(int32_t*& pCharWidths) { | |
| 647 int32_t iCount = m_pTxtBreak->CountBreakPieces(); | |
| 648 CFX_Char* pTC; | |
| 649 for (int32_t i = 0; i < iCount; i++) { | |
| 650 const CFX_TxtPiece* pPiece = m_pTxtBreak->GetBreakPiece(i); | |
| 651 int32_t iPieceChars = pPiece->GetLength(); | |
| 652 for (int32_t j = 0; j < iPieceChars; j++) { | |
| 653 pTC = pPiece->GetCharPtr(j); | |
| 654 if (pTC->m_iCharWidth <= 0) { | |
| 655 *pCharWidths = 0; | |
| 656 } else { | |
| 657 *pCharWidths = pTC->m_iCharWidth; | |
| 658 } | |
| 659 m_iEllipsisWidth += *pCharWidths; | |
| 660 pCharWidths++; | |
| 661 } | |
| 662 } | |
| 663 m_pTxtBreak->ClearBreakPieces(); | |
| 664 } | |
| 665 void CFDE_TextOut::LoadText(const FX_WCHAR* pwsStr, | |
| 666 int32_t iLength, | |
| 667 const CFX_RectF& rect) { | |
| 668 FX_WCHAR* pStr = m_wsText.GetBuffer(iLength); | |
| 669 int32_t iTxtLength = iLength; | |
| 670 ExpandBuffer(iTxtLength, 0); | |
| 671 FX_BOOL bHotKey = !!(m_dwStyles & FDE_TTOSTYLE_HotKey); | |
| 672 FX_BOOL bVertical = !!(m_dwStyles & FDE_TTOSTYLE_VerticalLayout); | |
| 673 FX_BOOL bLineWrap = !!(m_dwStyles & FDE_TTOSTYLE_LineWrap); | |
| 674 FX_FLOAT fLineStep = | |
| 675 (m_fLineSpace > m_fFontSize) ? m_fLineSpace : m_fFontSize; | |
| 676 FX_FLOAT fLineStop = bVertical ? rect.left : rect.bottom(); | |
| 677 m_fLinePos = bVertical ? rect.right() : rect.top; | |
| 678 if (bVertical) { | |
| 679 fLineStep = -fLineStep; | |
| 680 } | |
| 681 m_hotKeys.RemoveAll(); | |
| 682 int32_t iStartChar = 0; | |
| 683 int32_t iChars = 0; | |
| 684 int32_t iPieceWidths = 0; | |
| 685 FX_DWORD dwBreakStatus; | |
| 686 FX_WCHAR wch; | |
| 687 FX_BOOL bRet = FALSE; | |
| 688 while (iTxtLength-- > 0) { | |
| 689 wch = *pwsStr++; | |
| 690 if (wch == L'&' && bHotKey && (pStr - 1) != NULL && *(pStr - 1) != L'&') { | |
| 691 if (iTxtLength > 0) { | |
| 692 m_hotKeys.Add(iChars); | |
| 693 } | |
| 694 continue; | |
| 695 } | |
| 696 *pStr++ = wch; | |
| 697 iChars++; | |
| 698 dwBreakStatus = m_pTxtBreak->AppendChar(wch); | |
| 699 if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { | |
| 700 FX_BOOL bEndofLine = | |
| 701 RetriecePieces(dwBreakStatus, iStartChar, iPieceWidths, FALSE, rect); | |
| 702 if (bEndofLine && (bLineWrap || (dwBreakStatus > FX_TXTBREAK_LineBreak && | |
| 703 !bLineWrap))) { | |
| 704 iPieceWidths = 0; | |
| 705 m_iCurLine++; | |
| 706 m_fLinePos += fLineStep; | |
| 707 } | |
| 708 if ((bVertical && m_fLinePos + fLineStep < fLineStop) || | |
| 709 (!bVertical && m_fLinePos + fLineStep > fLineStop)) { | |
| 710 int32_t iCurLine = m_iCurLine; | |
| 711 if (bEndofLine) { | |
| 712 iCurLine--; | |
| 713 } | |
| 714 CFDE_TTOLine* pLine = m_ttoLines.GetPtrAt(iCurLine); | |
| 715 pLine->m_bNewReload = TRUE; | |
| 716 bRet = TRUE; | |
| 717 break; | |
| 718 } | |
| 719 } | |
| 720 } | |
| 721 dwBreakStatus = m_pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); | |
| 722 if (dwBreakStatus > FX_TXTBREAK_PieceBreak && !bRet) { | |
| 723 RetriecePieces(dwBreakStatus, iStartChar, iPieceWidths, FALSE, rect); | |
| 724 } | |
| 725 m_pTxtBreak->ClearBreakPieces(); | |
| 726 m_pTxtBreak->Reset(); | |
| 727 m_wsText.ReleaseBuffer(iLength); | |
| 728 } | |
| 729 FX_BOOL CFDE_TextOut::RetriecePieces(FX_DWORD dwBreakStatus, | |
| 730 int32_t& iStartChar, | |
| 731 int32_t& iPieceWidths, | |
| 732 FX_BOOL bReload, | |
| 733 const CFX_RectF& rect) { | |
| 734 FX_BOOL bSingleLine = !!(m_dwStyles & FDE_TTOSTYLE_SingleLine); | |
| 735 FX_BOOL bLineWrap = !!(m_dwStyles & FDE_TTOSTYLE_LineWrap); | |
| 736 FX_BOOL bVertical = !!(m_dwStyles & FDE_TTOSTYLE_VerticalLayout); | |
| 737 FX_FLOAT fLineStep = | |
| 738 (m_fLineSpace > m_fFontSize) ? m_fLineSpace : m_fFontSize; | |
| 739 if (bVertical) { | |
| 740 fLineStep = -fLineStep; | |
| 741 } | |
| 742 CFX_Char* pTC = NULL; | |
| 743 FX_BOOL bNeedReload = FALSE; | |
| 744 FX_FLOAT fLineWidth = bVertical ? rect.Height() : rect.Width(); | |
| 745 int32_t iLineWidth = FXSYS_round(fLineWidth * 20000.0f); | |
| 746 int32_t iCount = m_pTxtBreak->CountBreakPieces(); | |
| 747 for (int32_t i = 0; i < iCount; i++) { | |
| 748 const CFX_TxtPiece* pPiece = m_pTxtBreak->GetBreakPiece(i); | |
| 749 int32_t iPieceChars = pPiece->GetLength(); | |
| 750 int32_t iChar = iStartChar; | |
| 751 int32_t iWidth = 0; | |
| 752 int32_t j = 0; | |
| 753 for (; j < iPieceChars; j++) { | |
| 754 pTC = pPiece->GetCharPtr(j); | |
| 755 int32_t iCurCharWidth = pTC->m_iCharWidth > 0 ? pTC->m_iCharWidth : 0; | |
| 756 if (bSingleLine || !bLineWrap) { | |
| 757 if (iLineWidth - iPieceWidths - iWidth < iCurCharWidth) { | |
| 758 bNeedReload = TRUE; | |
| 759 break; | |
| 760 } | |
| 761 } | |
| 762 iWidth += iCurCharWidth; | |
| 763 m_pCharWidths[iChar++] = iCurCharWidth; | |
| 764 } | |
| 765 if (j == 0 && !bReload) { | |
| 766 CFDE_TTOLine* pLine = m_ttoLines.GetPtrAt(m_iCurLine); | |
| 767 pLine->m_bNewReload = TRUE; | |
| 768 } else if (j > 0) { | |
| 769 CFX_RectF rtPiece; | |
| 770 if (bVertical) { | |
| 771 rtPiece.left = m_fLinePos; | |
| 772 rtPiece.top = rect.top + (FX_FLOAT)pPiece->m_iStartPos / 20000.0f; | |
| 773 rtPiece.width = fLineStep; | |
| 774 rtPiece.height = iWidth / 20000.0f; | |
| 775 } else { | |
| 776 rtPiece.left = rect.left + (FX_FLOAT)pPiece->m_iStartPos / 20000.0f; | |
| 777 rtPiece.top = m_fLinePos; | |
| 778 rtPiece.width = iWidth / 20000.0f; | |
| 779 rtPiece.height = fLineStep; | |
| 780 } | |
| 781 FDE_TTOPIECE ttoPiece; | |
| 782 ttoPiece.iStartChar = iStartChar; | |
| 783 ttoPiece.iChars = j; | |
| 784 ttoPiece.rtPiece = rtPiece; | |
| 785 ttoPiece.dwCharStyles = pPiece->m_dwCharStyles; | |
| 786 if (FX_IsOdd(pPiece->m_iBidiLevel)) { | |
| 787 ttoPiece.dwCharStyles |= FX_TXTCHARSTYLE_OddBidiLevel; | |
| 788 } | |
| 789 AppendPiece(ttoPiece, bNeedReload, (bReload && i == iCount - 1)); | |
| 790 } | |
| 791 iStartChar += iPieceChars; | |
| 792 iPieceWidths += iWidth; | |
| 793 } | |
| 794 m_pTxtBreak->ClearBreakPieces(); | |
| 795 FX_BOOL bRet = bSingleLine || bLineWrap || (!bLineWrap && bNeedReload) || | |
| 796 dwBreakStatus == FX_TXTBREAK_ParagraphBreak; | |
| 797 return bRet; | |
| 798 } | |
| 799 void CFDE_TextOut::AppendPiece(const FDE_TTOPIECE& ttoPiece, | |
| 800 FX_BOOL bNeedReload, | |
| 801 FX_BOOL bEnd) { | |
| 802 if (m_iCurLine >= m_ttoLines.GetSize()) { | |
| 803 CFDE_TTOLine ttoLine; | |
| 804 ttoLine.m_bNewReload = bNeedReload; | |
| 805 m_iCurPiece = ttoLine.AddPiece(m_iCurPiece, ttoPiece); | |
| 806 m_iCurLine = m_ttoLines.Add(ttoLine); | |
| 807 } else { | |
| 808 CFDE_TTOLine* pLine = m_ttoLines.GetPtrAt(m_iCurLine); | |
| 809 pLine->m_bNewReload = bNeedReload; | |
| 810 m_iCurPiece = pLine->AddPiece(m_iCurPiece, ttoPiece); | |
| 811 if (bEnd) { | |
| 812 int32_t iPieces = pLine->GetSize(); | |
| 813 if (m_iCurPiece < iPieces) { | |
| 814 pLine->RemoveLast(iPieces - m_iCurPiece - 1); | |
| 815 } | |
| 816 } | |
| 817 } | |
| 818 if (!bEnd && bNeedReload) { | |
| 819 m_iCurPiece = 0; | |
| 820 } | |
| 821 } | |
| 822 void CFDE_TextOut::ReplaceWidthEllipsis() { | |
| 823 LoadEllipsis(); | |
| 824 int32_t iLength = m_wsEllipsis.GetLength(); | |
| 825 if (iLength < 1) { | |
| 826 return; | |
| 827 } | |
| 828 int32_t iLines = m_ttoLines.GetSize(); | |
| 829 for (int32_t i = 0; i < iLines; i++) { | |
| 830 CFDE_TTOLine* pLine = m_ttoLines.GetPtrAt(i); | |
| 831 if (!pLine->m_bNewReload) { | |
| 832 continue; | |
| 833 } | |
| 834 int32_t iEllipsisCharIndex = iLength - 1; | |
| 835 int32_t iCharWidth = 0; | |
| 836 int32_t iCharCount = 0; | |
| 837 int32_t iPiece = pLine->GetSize(); | |
| 838 while (iPiece-- > 0) { | |
| 839 FDE_LPTTOPIECE pPiece = pLine->GetPtrAt(iPiece); | |
| 840 if (pPiece == NULL) { | |
| 841 break; | |
| 842 } | |
| 843 for (int32_t j = pPiece->iChars - 1; j >= 0; j--) { | |
| 844 if (iEllipsisCharIndex < 0) { | |
| 845 break; | |
| 846 } | |
| 847 int32_t index = pPiece->iStartChar + j; | |
| 848 iCharWidth += m_pCharWidths[index]; | |
| 849 iCharCount++; | |
| 850 if (iCharCount <= iLength) { | |
| 851 m_wsText.SetAt(index, m_wsEllipsis.GetAt(iEllipsisCharIndex)); | |
| 852 m_pCharWidths[index] = m_pEllCharWidths[iEllipsisCharIndex]; | |
| 853 } else if (iCharWidth <= m_iEllipsisWidth) { | |
| 854 m_wsText.SetAt(index, 0); | |
| 855 m_pCharWidths[index] = 0; | |
| 856 } | |
| 857 iEllipsisCharIndex--; | |
| 858 } | |
| 859 if (iEllipsisCharIndex < 0) { | |
| 860 break; | |
| 861 } | |
| 862 } | |
| 863 } | |
| 864 } | |
| 865 void CFDE_TextOut::Reload(const CFX_RectF& rect) { | |
| 866 int32_t iCount = m_ttoLines.GetSize(); | |
| 867 for (int32_t i = 0; i < iCount; i++) { | |
| 868 CFDE_TTOLine* pLine = m_ttoLines.GetPtrAt(i); | |
| 869 if (pLine == NULL || !pLine->m_bNewReload) { | |
| 870 continue; | |
| 871 } | |
| 872 m_iCurLine = i; | |
| 873 m_iCurPiece = 0; | |
| 874 ReloadLinePiece(pLine, rect); | |
| 875 } | |
| 876 } | |
| 877 void CFDE_TextOut::ReloadLinePiece(CFDE_TTOLine* pLine, const CFX_RectF& rect) { | |
| 878 const FX_WCHAR* pwsStr = (const FX_WCHAR*)m_wsText; | |
| 879 FX_BOOL bVertical = !!(m_dwStyles & FDE_TTOSTYLE_VerticalLayout); | |
| 880 int32_t iPieceWidths = 0; | |
| 881 FDE_LPTTOPIECE pPiece = pLine->GetPtrAt(0); | |
| 882 int32_t iStartChar = pPiece->iStartChar; | |
| 883 m_fLinePos = bVertical ? pPiece->rtPiece.left : pPiece->rtPiece.top; | |
| 884 int32_t iPieceCount = pLine->GetSize(); | |
| 885 int32_t iPieceIndex = 0; | |
| 886 FX_DWORD dwBreakStatus = 0; | |
| 887 FX_WCHAR wch; | |
| 888 while (iPieceIndex < iPieceCount) { | |
| 889 int32_t iStar = iStartChar; | |
| 890 int32_t iEnd = pPiece->iChars + iStar; | |
| 891 while (iStar < iEnd) { | |
| 892 wch = *(pwsStr + iStar); | |
| 893 dwBreakStatus = m_pTxtBreak->AppendChar(wch); | |
| 894 if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { | |
| 895 RetriecePieces(dwBreakStatus, iStartChar, iPieceWidths, TRUE, rect); | |
| 896 } | |
| 897 iStar++; | |
| 898 } | |
| 899 iPieceIndex++; | |
| 900 pPiece = pLine->GetPtrAt(iPieceIndex); | |
| 901 } | |
| 902 dwBreakStatus = m_pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); | |
| 903 if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { | |
| 904 RetriecePieces(dwBreakStatus, iStartChar, iPieceWidths, TRUE, rect); | |
| 905 } | |
| 906 m_pTxtBreak->Reset(); | |
| 907 } | |
| 908 void CFDE_TextOut::DoAlignment(const CFX_RectF& rect) { | |
| 909 FX_BOOL bVertical = !!(m_dwStyles & FDE_TTOSTYLE_VerticalLayout); | |
| 910 FX_FLOAT fLineStopS = bVertical ? rect.right() : rect.bottom(); | |
| 911 int32_t iLines = m_ttoLines.GetSize(); | |
| 912 if (iLines < 1) { | |
| 913 return; | |
| 914 } | |
| 915 CFDE_TTOLine* pLine = m_ttoLines.GetPtrAt(iLines - 1); | |
| 916 FDE_LPTTOPIECE pPiece = pLine->GetPtrAt(0); | |
| 917 if (pPiece == NULL) { | |
| 918 return; | |
| 919 } | |
| 920 FX_FLOAT fLineStopD = | |
| 921 bVertical ? pPiece->rtPiece.right() : pPiece->rtPiece.bottom(); | |
| 922 FX_FLOAT fInc = fLineStopS - fLineStopD; | |
| 923 if (m_iAlignment >= FDE_TTOALIGNMENT_CenterLeft && | |
| 924 m_iAlignment < FDE_TTOALIGNMENT_BottomLeft) { | |
| 925 fInc /= 2.0f; | |
| 926 } else if (m_iAlignment < FDE_TTOALIGNMENT_CenterLeft) { | |
| 927 fInc = 0.0f; | |
| 928 } | |
| 929 if (fInc < 1.0f) { | |
| 930 return; | |
| 931 } | |
| 932 for (int32_t i = 0; i < iLines; i++) { | |
| 933 CFDE_TTOLine* pLine = m_ttoLines.GetPtrAt(i); | |
| 934 int32_t iPieces = pLine->GetSize(); | |
| 935 for (int32_t j = 0; j < iPieces; j++) { | |
| 936 FDE_LPTTOPIECE pPiece = pLine->GetPtrAt(j); | |
| 937 if (bVertical) { | |
| 938 pPiece->rtPiece.left += fInc; | |
| 939 } else { | |
| 940 pPiece->rtPiece.top += fInc; | |
| 941 } | |
| 942 } | |
| 943 } | |
| 944 } | |
| 945 void CFDE_TextOut::OnDraw(const CFX_RectF& rtClip) { | |
| 946 if (m_pRenderDevice == NULL) { | |
| 947 return; | |
| 948 } | |
| 949 int32_t iLines = m_ttoLines.GetSize(); | |
| 950 if (iLines < 1) { | |
| 951 return; | |
| 952 } | |
| 953 IFDE_SolidBrush* pBrush = | |
| 954 (IFDE_SolidBrush*)IFDE_Brush::Create(FDE_BRUSHTYPE_Solid); | |
| 955 pBrush->SetColor(m_TxtColor); | |
| 956 IFDE_Pen* pPen = NULL; | |
| 957 FDE_HDEVICESTATE hDev = m_pRenderDevice->SaveState(); | |
| 958 if (rtClip.Width() > 0.0f && rtClip.Height() > 0.0f) { | |
| 959 m_pRenderDevice->SetClipRect(rtClip); | |
| 960 } | |
| 961 for (int32_t i = 0; i < iLines; i++) { | |
| 962 CFDE_TTOLine* pLine = m_ttoLines.GetPtrAt(i); | |
| 963 int32_t iPieces = pLine->GetSize(); | |
| 964 for (int32_t j = 0; j < iPieces; j++) { | |
| 965 FDE_LPTTOPIECE pPiece = pLine->GetPtrAt(j); | |
| 966 if (pPiece == NULL) { | |
| 967 continue; | |
| 968 } | |
| 969 int32_t iCount = GetDisplayPos(pPiece); | |
| 970 if (iCount > 0) { | |
| 971 m_pRenderDevice->DrawString(pBrush, m_pFont, m_pCharPos, iCount, | |
| 972 m_fFontSize, &m_Matrix); | |
| 973 } | |
| 974 DrawLine(pPiece, pPen); | |
| 975 } | |
| 976 } | |
| 977 m_pRenderDevice->RestoreState(hDev); | |
| 978 if (pBrush) { | |
| 979 pBrush->Release(); | |
| 980 } | |
| 981 if (pPen) { | |
| 982 pPen->Release(); | |
| 983 } | |
| 984 } | |
| 985 int32_t CFDE_TextOut::GetDisplayPos(FDE_LPTTOPIECE pPiece) { | |
| 986 FX_TXTRUN tr; | |
| 987 ToTextRun(pPiece, tr); | |
| 988 ExpandBuffer(tr.iLength, 2); | |
| 989 return m_pTxtBreak->GetDisplayPos(&tr, m_pCharPos); | |
| 990 } | |
| 991 int32_t CFDE_TextOut::GetCharRects(FDE_LPTTOPIECE pPiece) { | |
| 992 FX_TXTRUN tr; | |
| 993 ToTextRun(pPiece, tr); | |
| 994 m_rectArray.RemoveAll(); | |
| 995 return m_pTxtBreak->GetCharRects(&tr, m_rectArray); | |
| 996 } | |
| 997 void CFDE_TextOut::ToTextRun(const FDE_LPTTOPIECE pPiece, FX_TXTRUN& tr) { | |
| 998 tr.pAccess = NULL; | |
| 999 tr.pIdentity = NULL; | |
| 1000 tr.pStr = (const FX_WCHAR*)m_wsText + pPiece->iStartChar; | |
| 1001 tr.pWidths = m_pCharWidths + pPiece->iStartChar; | |
| 1002 tr.iLength = pPiece->iChars; | |
| 1003 tr.pFont = m_pFont; | |
| 1004 tr.fFontSize = m_fFontSize; | |
| 1005 tr.dwStyles = m_dwTxtBkStyles; | |
| 1006 tr.iCharRotation = 0; | |
| 1007 tr.dwCharStyles = pPiece->dwCharStyles; | |
| 1008 tr.wLineBreakChar = m_wParagraphBkChar; | |
| 1009 tr.pRect = &pPiece->rtPiece; | |
| 1010 } | |
| 1011 void CFDE_TextOut::DrawLine(const FDE_LPTTOPIECE pPiece, IFDE_Pen*& pPen) { | |
| 1012 FX_BOOL bUnderLine = !!(m_dwStyles & FDE_TTOSTYLE_Underline); | |
| 1013 FX_BOOL bStrikeOut = !!(m_dwStyles & FDE_TTOSTYLE_Strikeout); | |
| 1014 FX_BOOL bHotKey = !!(m_dwStyles & FDE_TTOSTYLE_HotKey); | |
| 1015 FX_BOOL bVertical = !!(m_dwStyles & FDE_TTOSTYLE_VerticalLayout); | |
| 1016 if (!bUnderLine && !bStrikeOut && !bHotKey) { | |
| 1017 return; | |
| 1018 } | |
| 1019 if (pPen == NULL) { | |
| 1020 pPen = IFDE_Pen::Create(); | |
| 1021 pPen->SetColor(m_TxtColor); | |
| 1022 } | |
| 1023 IFDE_Path* pPath = IFDE_Path::Create(); | |
| 1024 int32_t iLineCount = 0; | |
| 1025 CFX_RectF rtText = pPiece->rtPiece; | |
| 1026 CFX_PointF pt1, pt2; | |
| 1027 if (bUnderLine) { | |
| 1028 if (bVertical) { | |
| 1029 pt1.x = rtText.left; | |
| 1030 pt1.y = rtText.top; | |
| 1031 pt2.x = rtText.left; | |
| 1032 pt2.y = rtText.bottom(); | |
| 1033 } else { | |
| 1034 pt1.x = rtText.left; | |
| 1035 pt1.y = rtText.bottom(); | |
| 1036 pt2.x = rtText.right(); | |
| 1037 pt2.y = rtText.bottom(); | |
| 1038 } | |
| 1039 pPath->AddLine(pt1, pt2); | |
| 1040 iLineCount++; | |
| 1041 } | |
| 1042 if (bStrikeOut) { | |
| 1043 if (bVertical) { | |
| 1044 pt1.x = rtText.left + rtText.width * 2.0f / 5.0f; | |
| 1045 pt1.y = rtText.top; | |
| 1046 pt2.x = pt1.x; | |
| 1047 pt2.y = rtText.bottom(); | |
| 1048 } else { | |
| 1049 pt1.x = rtText.left; | |
| 1050 pt1.y = rtText.bottom() - rtText.height * 2.0f / 5.0f; | |
| 1051 pt2.x = rtText.right(); | |
| 1052 pt2.y = pt1.y; | |
| 1053 } | |
| 1054 pPath->AddLine(pt1, pt2); | |
| 1055 iLineCount++; | |
| 1056 } | |
| 1057 if (bHotKey) { | |
| 1058 int32_t iHotKeys = m_hotKeys.GetSize(); | |
| 1059 int32_t iCount = GetCharRects(pPiece); | |
| 1060 if (iCount > 0) { | |
| 1061 for (int32_t i = 0; i < iHotKeys; i++) { | |
| 1062 int32_t iCharIndex = m_hotKeys.GetAt(i); | |
| 1063 if (iCharIndex >= pPiece->iStartChar && | |
| 1064 iCharIndex < pPiece->iStartChar + pPiece->iChars) { | |
| 1065 CFX_RectF rect = m_rectArray.GetAt(iCharIndex - pPiece->iStartChar); | |
| 1066 if (bVertical) { | |
| 1067 pt1.x = rect.left; | |
| 1068 pt1.y = rect.top; | |
| 1069 pt2.x = rect.left; | |
| 1070 pt2.y = rect.bottom(); | |
| 1071 } else { | |
| 1072 pt1.x = rect.left; | |
| 1073 pt1.y = rect.bottom(); | |
| 1074 pt2.x = rect.right(); | |
| 1075 pt2.y = rect.bottom(); | |
| 1076 } | |
| 1077 pPath->AddLine(pt1, pt2); | |
| 1078 iLineCount++; | |
| 1079 } | |
| 1080 } | |
| 1081 } | |
| 1082 } | |
| 1083 if (iLineCount > 0) { | |
| 1084 m_pRenderDevice->DrawPath(pPen, 1, pPath, &m_Matrix); | |
| 1085 } | |
| 1086 pPath->Release(); | |
| 1087 } | |
| 1088 CFDE_TTOLine::CFDE_TTOLine() | |
| 1089 : m_bNewReload(FALSE), m_pieces(5), m_iPieceCount(0) {} | |
| 1090 CFDE_TTOLine::CFDE_TTOLine(const CFDE_TTOLine& ttoLine) : m_pieces(5) { | |
| 1091 m_bNewReload = ttoLine.m_bNewReload; | |
| 1092 m_iPieceCount = ttoLine.m_iPieceCount; | |
| 1093 m_pieces.Copy(ttoLine.m_pieces); | |
| 1094 } | |
| 1095 CFDE_TTOLine::~CFDE_TTOLine() {} | |
| 1096 int32_t CFDE_TTOLine::AddPiece(int32_t index, const FDE_TTOPIECE& ttoPiece) { | |
| 1097 if (index >= m_iPieceCount) { | |
| 1098 index = m_pieces.Add(ttoPiece) + 1; | |
| 1099 m_iPieceCount++; | |
| 1100 } else { | |
| 1101 FDE_TTOPIECE& piece = m_pieces.GetAt(index); | |
| 1102 piece = ttoPiece; | |
| 1103 } | |
| 1104 return index; | |
| 1105 } | |
| 1106 int32_t CFDE_TTOLine::GetSize() const { | |
| 1107 return m_iPieceCount; | |
| 1108 } | |
| 1109 FDE_LPTTOPIECE CFDE_TTOLine::GetPtrAt(int32_t index) { | |
| 1110 if (index >= m_iPieceCount) { | |
| 1111 return NULL; | |
| 1112 } | |
| 1113 return m_pieces.GetPtrAt(index); | |
| 1114 } | |
| 1115 void CFDE_TTOLine::RemoveLast(int32_t iCount) { | |
| 1116 m_pieces.RemoveLast(iCount); | |
| 1117 } | |
| 1118 void CFDE_TTOLine::RemoveAll(FX_BOOL bLeaveMemory) { | |
| 1119 m_pieces.RemoveAll(bLeaveMemory); | |
| 1120 } | |
| OLD | NEW |