1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: font_TextWriterBase.cpp
4
5 Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Revision: 23177 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <cstdarg>
19 #include <cstdio>
20 #include <nn/types.h>
21 #include <nn/assert.h>
22 #include <nw/font/font_TextWriterBase.h>
23 #include <nw/font/font_TagProcessorBase.h>
24 #include <nw/ut/ut_Inlines.h>
25
26 #if defined(_MSC_VER) && _MSC_VER >= 1500
27 #include <malloc.h>
28
29 #define GET_FORMAT_BUFFER() \
30 reinterpret_cast<CharType*>((s_FormatBuffer != NULL) ? \
31 s_FormatBuffer: \
32 _alloca(s_FormatBufferSize))
33 #else
34 #include <alloca.h>
35
36 #define GET_FORMAT_BUFFER() \
37 reinterpret_cast<CharType*>((s_FormatBuffer != NULL) ? \
38 s_FormatBuffer: \
39 alloca(s_FormatBufferSize))
40 #endif
41
42
43 namespace nw {
44 namespace font {
45
46
47 /* ------------------------------------------------------------------------
48 クラス変数定義
49 ------------------------------------------------------------------------ */
50
51 template <typename CharType>
52 CharType* TextWriterBase<CharType>::s_FormatBuffer = NULL;
53
54 template <typename CharType>
55 std::size_t TextWriterBase<CharType>::s_FormatBufferSize = DEFAULT_FORMAT_BUFFER_SIZE;
56
57 template <typename CharType>
58 TagProcessorBase<CharType> TextWriterBase<CharType>::s_DefaultTagProcessor;
59
60 namespace
61 {
62
63 /*!--------------------------------------------------------------------------*
64 @brief 基点が中央であるときのカーソル位置補正の値を求めます。
65 半分の値が浮動小数点にならないように整数値に切り上げます。
66
67 @param[in] value 考慮する幅/高さ
68
69 @return 基点が中央であるときのカーソル位置補正の値を返します。
70 *---------------------------------------------------------------------------*/
71 inline
72 f32
AdjustCenterValue(f32 value)73 AdjustCenterValue(f32 value)
74 {
75 return math::FCeil(value * 0.5f);
76 }
77
78 } // namespace
79
80
81 /* =======================================================================
82 public
83 ======================================================================== */
84
85 /* ------------------------------------------------------------------------
86 コンストラクタ/デストラクタ
87 ------------------------------------------------------------------------ */
88
89 template <typename CharType>
TextWriterBase()90 TextWriterBase<CharType>::TextWriterBase()
91 : CharWriter(),
92 m_WidthLimit(FLT_MAX),
93 m_CharSpace(0),
94 m_LineSpace(0),
95 m_TabWidth (4),
96 m_DrawFlag(DEFAULT_DRAWFLAG),
97 m_TagProcessor(&s_DefaultTagProcessor)
98 {
99 }
100
101 template <typename CharType>
~TextWriterBase()102 TextWriterBase<CharType>::~TextWriterBase()
103 {
104 }
105
106
107
108
109
110 /* ------------------------------------------------------------------------
111 行間/文字間/タブ幅
112 ------------------------------------------------------------------------ */
113
114 template <typename CharType>
115 void
SetLineHeight(f32 height)116 TextWriterBase<CharType>::SetLineHeight(f32 height)
117 {
118 const Font* font = GetFont();
119 const int linefeed = font != NULL ? font->GetLineFeed(): 0;
120
121 m_LineSpace = height - linefeed * GetScaleV();
122 }
123
124 template <typename CharType>
125 f32
GetLineHeight() const126 TextWriterBase<CharType>::GetLineHeight() const
127 {
128 const Font* font = GetFont();
129 const int linefeed = font != NULL ? font->GetLineFeed(): 0;
130
131 return linefeed * GetScaleV() + m_LineSpace;
132 }
133
134
135
136
137
138
139 /* ------------------------------------------------------------------------
140 文字列サイズ計算
141 ------------------------------------------------------------------------ */
142
143 template <typename CharType>
144 f32
CalcFormatStringWidth(StreamType format,...) const145 TextWriterBase<CharType>::CalcFormatStringWidth(
146 StreamType format,
147 ...
148 ) const
149 {
150 NN_POINTER_ASSERT(format);
151
152 ut::Rect rect;
153 std::va_list vargs;
154 va_start(vargs, format);
155
156 CalcVStringRect(&rect, format, vargs);
157
158 va_end(vargs);
159 return rect.GetWidth();
160 }
161
162 template <typename CharType>
163 f32
CalcFormatStringHeight(StreamType format,...) const164 TextWriterBase<CharType>::CalcFormatStringHeight(
165 StreamType format,
166 ...
167 ) const
168 {
169 NN_POINTER_ASSERT(format);
170
171 ut::Rect rect;
172 std::va_list vargs;
173 va_start(vargs, format);
174
175 CalcVStringRect(&rect, format, vargs);
176
177 va_end(vargs);
178 return rect.GetHeight();
179 }
180
181 template <typename CharType>
182 void
CalcFormatStringRect(ut::Rect * pRect,StreamType format,...) const183 TextWriterBase<CharType>::CalcFormatStringRect(
184 ut::Rect* pRect,
185 StreamType format,
186 ...
187 ) const
188 {
189 NN_POINTER_ASSERT(pRect);
190 NN_POINTER_ASSERT(format);
191
192 std::va_list vargs;
193 va_start(vargs, format);
194
195 CalcVStringRect(pRect, format, vargs);
196
197 va_end(vargs);
198 }
199
200 template <typename CharType>
201 void
CalcVStringRect(ut::Rect * pRect,StreamType format,std::va_list args) const202 TextWriterBase<CharType>::CalcVStringRect(
203 ut::Rect* pRect,
204 StreamType format,
205 std::va_list args
206 ) const
207 {
208 NN_POINTER_ASSERT(pRect);
209 NN_POINTER_ASSERT(format);
210
211 CharType* buffer = GET_FORMAT_BUFFER();
212
213 int length = VSNPrintf(buffer, s_FormatBufferSize, format, args);
214 length = math::Min(length, int(s_FormatBufferSize - 1));
215 CalcStringRect(pRect, buffer, length);
216 }
217
218 template <typename CharType>
219 f32
CalcStringWidth(StreamType str,int length) const220 TextWriterBase<CharType>::CalcStringWidth(
221 StreamType str,
222 int length
223 ) const
224 {
225 NN_POINTER_ASSERT(str);
226 NW_FONT_MIN_ASSERT(length, 0);
227
228 ut::Rect rect;
229
230 CalcStringRect(&rect, str, length);
231
232 return rect.GetWidth();
233 }
234
235 template <typename CharType>
236 f32
CalcStringHeight(StreamType str,int length) const237 TextWriterBase<CharType>::CalcStringHeight(
238 StreamType str,
239 int length
240 ) const
241 {
242 NN_POINTER_ASSERT(str);
243 NW_FONT_MIN_ASSERT(length, 0);
244
245 ut::Rect rect;
246
247 CalcStringRect(&rect, str, length);
248
249 return rect.GetHeight();
250 }
251
252 template <typename CharType>
253 void
CalcStringRect(ut::Rect * pRect,StreamType str,int length) const254 TextWriterBase<CharType>::CalcStringRect(
255 ut::Rect* pRect,
256 StreamType str,
257 int length
258 ) const
259 {
260 NN_POINTER_ASSERT(pRect);
261 NN_POINTER_ASSERT(str);
262 NW_FONT_MIN_ASSERT(length, 0);
263
264 TextWriterBase<CharType> myCopy = *this;
265
266 myCopy.CalcStringRectImpl(pRect, str, length);
267
268 #if defined(NW_FONT_PROFILE)
269 this->CopyProfileData(myCopy);
270 #endif
271 }
272
273
274
275
276
277
278 /* ------------------------------------------------------------------------
279 文字列描画
280 ------------------------------------------------------------------------ */
281
282 template <typename CharType>
283 f32
Printf(StreamType format,...)284 TextWriterBase<CharType>::Printf(
285 StreamType format,
286 ...
287 )
288 {
289 NN_POINTER_ASSERT(format);
290
291 std::va_list vargs;
292 va_start(vargs, format);
293
294 f32 width = VPrintf(format, vargs);
295
296 va_end(vargs);
297 return width;
298 }
299
300 template <typename CharType>
301 f32
VPrintf(StreamType format,std::va_list args)302 TextWriterBase<CharType>::VPrintf(
303 StreamType format,
304 std::va_list args
305 )
306 {
307 NN_POINTER_ASSERT(format);
308
309 CharType* buffer = GET_FORMAT_BUFFER();
310
311 int length = VSNPrintf(buffer, s_FormatBufferSize, format, args);
312 length = math::Min(length, int(s_FormatBufferSize - 1));
313 f32 width = Print(buffer, length);
314
315 return width;
316 }
317
318 template <typename CharType>
319 f32
Print(StreamType str,int length)320 TextWriterBase<CharType>::Print(
321 StreamType str,
322 int length
323 )
324 {
325 NN_POINTER_ASSERT(str);
326 NW_FONT_MIN_ASSERT(length, 0);
327
328 NW_FONT_COUNTUP(m_PrintTextCount);
329 NW_FONT_STOPWATCH_START(m_PrintTextSw);
330
331 TextWriterBase<CharType> myCopy = *this;
332
333 f32 width = myCopy.PrintImpl(str, length);
334
335 SetCursor( myCopy.GetCursorX(), myCopy.GetCursorY() );
336
337 #if defined(NW_FONT_PROFILE)
338 this->CopyProfileData(myCopy);
339 #endif
340 NW_FONT_STOPWATCH_STOP(m_PrintTextSw);
341
342 return width;
343 }
344
345 /* =======================================================================
346 private
347 ======================================================================== */
348
349 /* ------------------------------------------------------------------------
350 文字列処理
351 ------------------------------------------------------------------------ */
352
353 template <typename CharType>
354 f32
CalcLineWidth(StreamType str,int length)355 TextWriterBase<CharType>::CalcLineWidth(
356 StreamType str,
357 int length
358 )
359 {
360 NN_POINTER_ASSERT(str);
361 NW_FONT_MIN_ASSERT(length, 0);
362
363 ut::Rect rect;
364 TextWriterBase<CharType> myCopy = *this;
365
366 myCopy.SetCursor(0, 0);
367 myCopy.CalcLineRectImpl(&rect, &str, length);
368
369 #if defined(NW_FONT_PROFILE)
370 this->CopyProfileData(myCopy);
371 #endif
372
373 return rect.GetWidth();
374 }
375
376 template <typename CharType>
377 bool
CalcLineRectImpl(ut::Rect * pRect,StreamType * pStr,int length)378 TextWriterBase<CharType>::CalcLineRectImpl(
379 ut::Rect* pRect,
380 StreamType* pStr,
381 int length
382 )
383 {
384 NN_POINTER_ASSERT(pRect);
385 NN_POINTER_ASSERT(pStr);
386 NN_POINTER_ASSERT(*pStr);
387 NW_FONT_MIN_ASSERT(length, 0);
388
389 const StreamType str = *pStr;
390 const StreamType end = str + length;
391 const bool bUseLimit = m_WidthLimit < FLT_MAX;
392 PrintContext<CharType> context(this, str, 0, 0, 0);
393 f32 limitLeft = 0;
394 f32 limitRight = 0;
395 bool bCharSpace = false;
396 bool bOverLimit = false;
397 StreamType prevStreamPos = NULL;
398 ut::Rect prevRect;
399
400 /*
401 文字列の途中でエンコーディングが変わる事は想定していない
402 */
403 NN_POINTER_ASSERT(GetFont());
404 CharStrmReader reader = GetFont()->GetCharStrmReader(CharType(0));
405
406 // 1行の高さにはLineSpaceを含めない。
407 f32 lineFeed = GetLineHeight() - GetLineSpace();
408
409 pRect->left = 0;
410 pRect->right = 0;
411 pRect->top = math::Min(0.0f, lineFeed);
412 pRect->bottom = math::Max(0.0f, lineFeed);
413 prevRect = *pRect;
414
415 reader.Set(str);
416 prevStreamPos = NULL;
417
418 for (
419 CharCode code = reader.Next();
420 reinterpret_cast<StreamType>(reader.GetCurrentPos()) <= end;
421 )
422 {
423 if (code < ' ')
424 {
425 //---- 制御文字(タグの開始)
426
427 typename TagProcessor::Operation operation;
428 ut::Rect rect(limitRight, 0, 0, 0);
429
430 context.str = reinterpret_cast<StreamType>(reader.GetCurrentPos());
431 context.flags = 0;
432 context.flags |= bCharSpace ? 0: CONTEXT_NO_CHAR_SPACE;
433 SetCursorX(limitRight);
434
435 //---- 折り返しの判定
436 if ( bUseLimit
437 && code != '\n'
438 && prevStreamPos != NULL
439 )
440 {
441 PrintContext<CharType> context2 = context;
442 TextWriterBase<CharType> myCopy = *this;
443 ut::Rect rect2;
444
445 context2.writer = &myCopy;
446 operation = m_TagProcessor->CalcRect(&rect2, code, &context2);
447
448 #if defined(NW_FONT_PROFILE)
449 this->CopyProfileData(myCopy);
450 #endif
451
452 if ( rect2.GetWidth() > 0.0f
453 && (myCopy.GetCursorX() - context.xOrigin > m_WidthLimit)
454 )
455 {
456 bOverLimit = true;
457 code = '\n';
458 reader.Set(prevStreamPos);
459 continue;
460 }
461 }
462
463 //---- タグ処理
464 operation = m_TagProcessor->CalcRect(&rect, code, &context);
465
466 NN_POINTER_ASSERT(context.str);
467 reader.Set(context.str);
468
469 pRect->left = math::Min(pRect->left, rect.left);
470 pRect->top = math::Min(pRect->top, rect.top);
471 pRect->right = math::Max(pRect->right, rect.right);
472 pRect->bottom = math::Max(pRect->bottom, rect.bottom);
473 limitRight = GetCursorX();
474
475 if (operation == TagProcessor::OPERATION_END_DRAW)
476 {
477 //---- 全部読み進んだ事にする
478 *pStr += length;
479 return false;
480 }
481 else if (operation == TagProcessor::OPERATION_NO_CHAR_SPACE)
482 {
483 bCharSpace = false;
484 }
485 else if (operation == TagProcessor::OPERATION_CHAR_SPACE)
486 {
487 bCharSpace = true;
488 }
489 else if (operation == TagProcessor::OPERATION_NEXT_LINE)
490 {
491 break;
492 }
493 }
494 else
495 {
496 //---- 通常の文字
497
498 f32 crntRight = limitRight;
499
500 if (bCharSpace)
501 {
502 crntRight += GetCharSpace();
503 }
504
505 if (IsWidthFixed())
506 {
507 crntRight += GetFixedWidth();
508 }
509 else
510 {
511 crntRight += GetFont()->GetCharWidth(code) * GetScaleH();
512 }
513
514 //---- 折り返しの判定
515 if (bUseLimit && prevStreamPos != NULL)
516 {
517 f32 width = crntRight - limitLeft;
518 if (width > m_WidthLimit)
519 {
520 bOverLimit = true;
521 code = '\n';
522 reader.Set(prevStreamPos);
523 continue;
524 }
525 }
526
527 limitRight = crntRight;
528 pRect->left = math::Min(pRect->left, limitRight);
529 pRect->right = math::Max(pRect->right, limitRight);
530 bCharSpace = true;
531 }
532
533 if (bUseLimit)
534 {
535 prevStreamPos = reinterpret_cast<StreamType>(reader.GetCurrentPos());
536 }
537
538 code = reader.Next();
539 }
540
541
542 *pStr = reinterpret_cast<StreamType>(reader.GetCurrentPos());
543
544 return bOverLimit;
545 }
546
547 template <typename CharType>
548 void
CalcStringRectImpl(ut::Rect * pRect,StreamType str,int length)549 TextWriterBase<CharType>::CalcStringRectImpl(
550 ut::Rect* pRect,
551 StreamType str,
552 int length
553 )
554 {
555 NN_POINTER_ASSERT(pRect);
556 NN_POINTER_ASSERT(str);
557 NW_FONT_MIN_ASSERT(length, 0);
558
559 const StreamType end = str + length;
560 int remain = length;
561 StreamType pos = str;
562
563 pRect->left = 0;
564 pRect->right = 0;
565 pRect->top = 0;
566 pRect->bottom = 0;
567
568 SetCursor(0, 0);
569
570 do
571 {
572 ut::Rect rect;
573 CalcLineRectImpl(&rect, &pos, remain);
574 remain = (end - pos);
575
576 pRect->left = math::Min(pRect->left, rect.left);
577 pRect->top = math::Min(pRect->top, rect.top);
578 pRect->right = math::Max(pRect->right, rect.right);
579 pRect->bottom = math::Max(pRect->bottom, rect.bottom);
580 } while (remain > 0);
581 }
582
583 template <typename CharType>
584 f32
PrintImpl(StreamType str,int length)585 TextWriterBase<CharType>::PrintImpl(
586 StreamType str,
587 int length
588 )
589 {
590 NN_POINTER_ASSERT(str);
591 NN_POINTER_ASSERT(GetFont());
592 NW_FONT_MIN_ASSERT(length, 0);
593
594 f32 xOrigin = GetCursorX();
595 f32 yOrigin = GetCursorY();
596 f32 limitLeft = 0;
597 f32 limitRight = 0;
598 const bool bUseLimit = m_WidthLimit < FLT_MAX;
599 const f32 orgCursorY = yOrigin;
600 bool bCharSpace = false;
601 StreamType prevStreamPos = str;
602 StreamType prevNewLinePos = str;
603
604 f32 textWidth = AdjustCursor(&xOrigin, &yOrigin, str, length);
605 f32 yCursorAdj = orgCursorY - GetCursorY();
606
607 PrintContext<CharType> context(this, str, xOrigin, yOrigin, 0);
608 CharStrmReader reader = GetFont()->GetCharStrmReader(CharType(0));
609 reader.Set(str);
610
611 for (
612 CharCode code = reader.Next();
613 reinterpret_cast<StreamType>(reader.GetCurrentPos()) - str <= length;
614 )
615 {
616 if (code < ' ')
617 {
618 //---- 制御文字(タグの開始)
619
620 typename TagProcessor::Operation operation;
621 context.str = reinterpret_cast<StreamType>(reader.GetCurrentPos());
622 context.flags = 0;
623 context.flags |= bCharSpace ? 0: CONTEXT_NO_CHAR_SPACE;
624
625 //---- 折り返しの判定
626 if ( bUseLimit
627 && code != '\n'
628 && prevStreamPos != prevNewLinePos
629 )
630 {
631 PrintContext<CharType> context2 = context;
632 TextWriterBase<CharType> myCopy = *this;
633 ut::Rect rect;
634
635 context2.writer = &myCopy;
636 operation = m_TagProcessor->CalcRect(&rect, code, &context2);
637
638 #if defined(NW_FONT_PROFILE)
639 this->CopyProfileData(myCopy);
640 #endif
641
642 if ( rect.GetWidth() > 0.0f
643 && myCopy.GetCursorX() - context.xOrigin > m_WidthLimit
644 )
645 {
646 code = '\n';
647 reader.Set(prevStreamPos);
648 continue;
649 }
650 }
651
652 //---- タグ処理
653 operation = m_TagProcessor->Process(code, &context);
654 limitRight = GetCursorX() - xOrigin;
655
656 if (operation == TagProcessor::OPERATION_NEXT_LINE)
657 {
658 NN_POINTER_ASSERT(context.str);
659
660 //---- 次行描画開始位置Xの補正
661 if (IsDrawFlagSet(HORIZONTAL_ALIGN_MASK, HORIZONTAL_ALIGN_CENTER))
662 {
663 const int remain = length - (context.str - str);
664 const f32 width = CalcLineWidth( context.str, remain );
665 const f32 offset = AdjustCenterValue(textWidth) - AdjustCenterValue(width);
666 SetCursorX( context.xOrigin + offset );
667 }
668 else if (IsDrawFlagSet(HORIZONTAL_ALIGN_MASK, HORIZONTAL_ALIGN_RIGHT))
669 {
670 const int remain = length - (context.str - str);
671 const f32 width = CalcLineWidth( context.str, remain );
672 const f32 offset = textWidth - width;
673 SetCursorX( context.xOrigin + offset );
674 }
675 else
676 {
677 //---- 最大幅の更新
678 const f32 width = GetCursorX() - context.xOrigin;
679 textWidth = math::Max(textWidth, width);
680
681 SetCursorX( context.xOrigin );
682 }
683
684 if (bUseLimit)
685 {
686 prevNewLinePos = reinterpret_cast<StreamType>(reader.GetCurrentPos());
687 }
688 bCharSpace = false;
689 }
690 else if (operation == TagProcessor::OPERATION_NO_CHAR_SPACE)
691 {
692 bCharSpace = false;
693 }
694 else if (operation == TagProcessor::OPERATION_CHAR_SPACE)
695 {
696 bCharSpace = true;
697 }
698 else if (operation == TagProcessor::OPERATION_END_DRAW)
699 {
700 break;
701 }
702
703 NN_POINTER_ASSERT(context.str);
704 reader.Set(context.str);
705 }
706 else
707 {
708 //---- 通常の文字
709
710 const f32 baseY = GetCursorY();
711
712 f32 crntRight = limitRight;
713
714 if (bCharSpace)
715 {
716 crntRight += GetCharSpace();
717 }
718
719 if (IsWidthFixed())
720 {
721 crntRight += GetFixedWidth();
722 }
723 else
724 {
725 crntRight += GetFont()->GetCharWidth(code) * GetScaleH();
726 }
727
728 //---- 折り返しの判定
729 if (bUseLimit && prevStreamPos != prevNewLinePos)
730 {
731 f32 width = crntRight - limitLeft;
732 if (width > m_WidthLimit)
733 {
734 code = '\n';
735 reader.Set(prevStreamPos);
736 continue;
737 }
738 }
739
740 limitRight = crntRight;
741
742
743 if (bCharSpace)
744 {
745 MoveCursorX( GetCharSpace() );
746 }
747 bCharSpace = true;
748
749
750 //---- カーソルはベースラインにあるのでセル上端へ移動する
751 {
752 const Font* pFont = GetFont();
753 const f32 adj = - pFont->GetBaselinePos() * GetScaleV();
754 MoveCursorY( adj );
755 }
756
757 Print(code);
758
759 // 戻す
760 SetCursorY( baseY );
761 }
762
763 if (bUseLimit)
764 {
765 prevStreamPos = reinterpret_cast<StreamType>(reader.GetCurrentPos());
766 }
767
768 code = reader.Next();
769 }
770
771 //---- 最大幅の更新
772 {
773 const f32 width = GetCursorX() - context.xOrigin;
774 textWidth = math::Max(textWidth, width);
775 }
776
777 //---- カーソル位置Yを描画フラグに従って移動
778 // AdjustCursorでベースライン上に移動したカーソル位置を元に戻す
779 if ( IsDrawFlagSet(VERTICAL_ORIGIN_MASK, VERTICAL_ORIGIN_MIDDLE)
780 || IsDrawFlagSet(VERTICAL_ORIGIN_MASK, VERTICAL_ORIGIN_BOTTOM)
781 )
782 {
783 SetCursorY(orgCursorY);
784 }
785 else
786 {
787 MoveCursorY(yCursorAdj);
788 }
789
790 return textWidth;
791 }
792
793 template <typename CharType>
794 f32
AdjustCursor(f32 * pXOrigin,f32 * pYOrigin,StreamType str,int length)795 TextWriterBase<CharType>::AdjustCursor(
796 f32* pXOrigin,
797 f32* pYOrigin,
798 StreamType str,
799 int length
800 )
801 {
802 f32 textWidth = 0;
803 f32 textHeight = 0;
804
805 {
806 u32 flagMask = HORIZONTAL_ALIGN_MASK | HORIZONTAL_ORIGIN_MASK | VERTICAL_ORIGIN_MASK;
807 u32 blineFlag = HORIZONTAL_ALIGN_LEFT | HORIZONTAL_ORIGIN_LEFT | VERTICAL_ORIGIN_BASELINE;
808 u32 topFlag = HORIZONTAL_ALIGN_LEFT | HORIZONTAL_ORIGIN_LEFT | VERTICAL_ORIGIN_TOP;
809
810 if ( ! IsDrawFlagSet(flagMask, blineFlag)
811 && ! IsDrawFlagSet(flagMask, topFlag)
812 )
813 {
814 ut::Rect textRect;
815 CalcStringRect(&textRect, str, length);
816 textWidth = textRect.left + textRect.right;
817 textHeight = textRect.top + textRect.bottom;
818 }
819 }
820
821 //---- 描画開始位置Xの補正
822 // 各々の位置から文字列の左端に統一
823 if (IsDrawFlagSet(HORIZONTAL_ORIGIN_MASK, HORIZONTAL_ORIGIN_CENTER))
824 {
825 *pXOrigin -= AdjustCenterValue(textWidth);
826 }
827 else if (IsDrawFlagSet(HORIZONTAL_ORIGIN_MASK, HORIZONTAL_ORIGIN_RIGHT))
828 {
829 *pXOrigin -= textWidth;
830 }
831
832 //---- 描画開始位置Yの補正
833 // 各々の位置から 1 行目のアセンダラインに統一
834 if (IsDrawFlagSet(VERTICAL_ORIGIN_MASK, VERTICAL_ORIGIN_MIDDLE))
835 {
836 *pYOrigin -= AdjustCenterValue(textHeight);
837 }
838 else if (IsDrawFlagSet(VERTICAL_ORIGIN_MASK, VERTICAL_ORIGIN_BOTTOM))
839 {
840 *pYOrigin -= textHeight;
841 }
842
843 //---- 1行目描画開始位置Xの補正
844 // 文字列の左端からそれぞれの寄せ位置へカーソルを移動
845 if (IsDrawFlagSet(HORIZONTAL_ALIGN_MASK, HORIZONTAL_ALIGN_CENTER))
846 {
847 const f32 width = CalcLineWidth(str, length);
848 const f32 offset = AdjustCenterValue(textWidth) - AdjustCenterValue(width);
849 SetCursorX( *pXOrigin + offset );
850 }
851 else if (IsDrawFlagSet(HORIZONTAL_ALIGN_MASK, HORIZONTAL_ALIGN_RIGHT))
852 {
853 const f32 width = CalcLineWidth(str, length);
854 const f32 offset = textWidth - width;
855 SetCursorX( *pXOrigin + offset );
856 }
857 else
858 {
859 SetCursorX( *pXOrigin );
860 }
861
862 //---- 1行目描画開始位置Yの補正
863 // 1 行目のベースライン位置にカーソルを移動
864 if (IsDrawFlagSet(VERTICAL_ORIGIN_MASK, VERTICAL_ORIGIN_BASELINE))
865 {
866 // pYOrigin はベースラインであるのでそのままセット
867 SetCursorY( *pYOrigin );
868 }
869 else
870 {
871 // pYOrigin はアセンダラインであるのでベースラインにカーソルを移動
872 SetCursorY( *pYOrigin + GetFontAscent() );
873 }
874
875 return textWidth;
876 }
877
878
879 #if defined(NW_FONT_PROFILE)
880 template <typename CharType>
881 void
PrintProfile()882 TextWriterBase<CharType>::PrintProfile()
883 {
884 using namespace nn::fnd;
885
886 CharWriter::PrintProfile();
887
888 TimeSpan timeSpan = m_PrintTextSw.GetElapsedTime();
889 NN_LOG("TextWriter Print time %d micros, count %d.\n", (int)timeSpan.GetMilliSeconds(), m_PrintTextCount);
890 }
891
892 template <typename CharType>
893 void
CopyProfileData(const TextWriterBase<CharType> & other) const894 TextWriterBase<CharType>::CopyProfileData(const TextWriterBase<CharType>& other) const
895 {
896 CharWriter::CopyProfileData(other);
897
898 m_PrintTextSw = other.m_PrintTextSw;
899 m_PrintTextCount = other.m_PrintTextCount;
900 }
901 #endif
902
903
904 /* =======================================================================
905 明示的実体化
906 ======================================================================== */
907
908 template class TextWriterBase<char>;
909 template class TextWriterBase<wchar_t>;
910
911
912
913 } // namespace font
914 } // namespace nw
915
916