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