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 |