1 // This file is part of VSTGUI. It is subject to the license terms
2 // in the LICENSE file found in the top-level directory of this
3 // distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
4 
5 #include "cdrawmethods.h"
6 #include "cbitmap.h"
7 #include "cstring.h"
8 #include "cdrawcontext.h"
9 #include "platform/iplatformfont.h"
10 
11 namespace VSTGUI {
12 namespace CDrawMethods {
13 
14 //------------------------------------------------------------------------
createTruncatedText(TextTruncateMode mode,const UTF8String & text,CFontRef font,CCoord maxWidth,const CPoint & textInset,uint32_t flags)15 UTF8String createTruncatedText (TextTruncateMode mode, const UTF8String& text, CFontRef font,
16                                 CCoord maxWidth, const CPoint& textInset, uint32_t flags)
17 {
18 	if (mode == kTextTruncateNone)
19 		return text;
20 	auto painter = font->getPlatformFont () ? font->getPlatformFont ()->getPainter () : nullptr;
21 	if (!painter)
22 		return text;
23 	CCoord width = painter->getStringWidth (nullptr, text.getPlatformString (), true);
24 	width += textInset.x * 2;
25 	if (width > maxWidth)
26 	{
27 		std::string truncatedText;
28 		UTF8String result;
29 		auto left = text.begin ();
30 		auto right = text.end ();
31 		while (width > maxWidth && left != right)
32 		{
33 			if (mode == kTextTruncateHead)
34 			{
35 				++left;
36 				truncatedText = "..";
37 			}
38 			else if (mode == kTextTruncateTail)
39 			{
40 				--right;
41 				truncatedText = "";
42 			}
43 
44 			truncatedText += {left.base (), right.base ()};
45 
46 			if (mode == kTextTruncateTail)
47 				truncatedText += "..";
48 
49 			result = truncatedText;
50 			width = painter->getStringWidth (nullptr, result.getPlatformString (), true);
51 			width += textInset.x * 2;
52 		}
53 		if (left == right && flags & kReturnEmptyIfTruncationIsPlaceholderOnly)
54 			result = "";
55 		return result;
56 	}
57 	return text;
58 }
59 
60 //------------------------------------------------------------------------
drawIconAndText(CDrawContext * context,CBitmap * iconToDraw,IconPosition iconPosition,CHoriTxtAlign textAlignment,CCoord textIconMargin,CRect drawRect,const UTF8String & title,CFontRef font,CColor textColor,TextTruncateMode textTruncateMode)61 void drawIconAndText (CDrawContext* context, CBitmap* iconToDraw, IconPosition iconPosition,
62                       CHoriTxtAlign textAlignment, CCoord textIconMargin, CRect drawRect,
63                       const UTF8String& title, CFontRef font, CColor textColor,
64                       TextTruncateMode textTruncateMode)
65 {
66 	if (iconToDraw)
67 	{
68 		CRect iconRect (0, 0, iconToDraw->getWidth (), iconToDraw->getHeight ());
69 		iconRect.offset (drawRect.left, drawRect.top);
70 		switch (iconPosition)
71 		{
72 			case kIconLeft:
73 			{
74 				iconRect.offset (textIconMargin,
75 				                 drawRect.getHeight () / 2. - iconRect.getHeight () / 2.);
76 				drawRect.left = iconRect.right;
77 				drawRect.right -= textIconMargin;
78 				if (textAlignment == kLeftText)
79 					drawRect.left += textIconMargin;
80 				break;
81 			}
82 			case kIconRight:
83 			{
84 				iconRect.offset (drawRect.getWidth () - (textIconMargin + iconRect.getWidth ()),
85 				                 drawRect.getHeight () / 2. - iconRect.getHeight () / 2.);
86 				drawRect.right = iconRect.left;
87 				drawRect.left += textIconMargin;
88 				if (textAlignment == kRightText)
89 					drawRect.right -= textIconMargin;
90 				break;
91 			}
92 			case kIconCenterAbove:
93 			{
94 				iconRect.offset (drawRect.getWidth () / 2. - iconRect.getWidth () / 2., 0);
95 				if (title.empty ())
96 					iconRect.offset (0, drawRect.getHeight () / 2. - iconRect.getHeight () / 2.);
97 				else
98 				{
99 					iconRect.offset (0, drawRect.getHeight () / 2. -
100 					                        (iconRect.getHeight () / 2. +
101 					                         (textIconMargin + font->getSize ()) / 2.));
102 					drawRect.top = iconRect.bottom + textIconMargin;
103 					drawRect.setHeight (font->getSize ());
104 					if (textAlignment == kLeftText)
105 						drawRect.left += textIconMargin;
106 					else if (textAlignment == kRightText)
107 						drawRect.right -= textIconMargin;
108 				}
109 				break;
110 			}
111 			case kIconCenterBelow:
112 			{
113 				iconRect.offset (drawRect.getWidth () / 2. - iconRect.getWidth () / 2., 0);
114 				if (title.empty ())
115 					iconRect.offset (0, drawRect.getHeight () / 2. - iconRect.getHeight () / 2.);
116 				else
117 				{
118 					iconRect.offset (0, drawRect.getHeight () / 2. - (iconRect.getHeight () / 2.) +
119 					                        (textIconMargin + font->getSize ()) / 2.);
120 					drawRect.top = iconRect.top - (textIconMargin + font->getSize ());
121 					drawRect.setHeight (font->getSize ());
122 					if (textAlignment == kLeftText)
123 						drawRect.left += textIconMargin;
124 					else if (textAlignment == kRightText)
125 						drawRect.right -= textIconMargin;
126 				}
127 				break;
128 			}
129 		}
130 		context->drawBitmap (iconToDraw, iconRect);
131 	}
132 	else
133 	{
134 		if (textAlignment == kLeftText)
135 			drawRect.left += textIconMargin;
136 		else if (textAlignment == kRightText)
137 			drawRect.right -= textIconMargin;
138 	}
139 	if (!title.empty ())
140 	{
141 		context->setFont (font);
142 		context->setFontColor (textColor);
143 		if (textTruncateMode != kTextTruncateNone)
144 		{
145 			UTF8String truncatedText =
146 			    createTruncatedText (textTruncateMode, title, font, drawRect.getWidth (),
147 			                         CPoint (0, 0), kReturnEmptyIfTruncationIsPlaceholderOnly);
148 			context->drawString (truncatedText.getPlatformString (), drawRect, textAlignment);
149 		}
150 		else
151 			context->drawString (title.getPlatformString (), drawRect, textAlignment);
152 	}
153 }
154 }
155 } // namespaces
156