Files
2026-08-16 18:24:52 +07:00

184 lines
5.6 KiB
C++

// This file is part of VSTGUI. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this
// distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
#include "cdrawmethods.h"
#include "cbitmap.h"
#include "cstring.h"
#include "cdrawcontext.h"
#include "platform/iplatformfont.h"
namespace VSTGUI {
namespace CDrawMethods {
//------------------------------------------------------------------------
UTF8String createTruncatedText (TextTruncateMode mode, const UTF8String& text, CFontRef font,
CCoord maxWidth, const CPoint& textInset, uint32_t flags)
{
if (mode == kTextTruncateNone || text.length () < 2)
return text;
auto painter = font->getPlatformFont () ? font->getPlatformFont ()->getPainter () : nullptr;
if (!painter)
return text;
CCoord width = painter->getStringWidth (nullptr, text.getPlatformString (), true);
width += textInset.x * 2;
if (width > maxWidth)
{
std::string truncatedText;
UTF8String result;
auto left = text.begin ();
auto right = text.end ();
size_t distance = std::distance (left, right) - 1;
int32_t dir = 1;
while (distance > 0 && width != maxWidth)
{
distance = (distance / 2);
while ((dir > 0 ? (width > maxWidth) : (width < maxWidth)) && distance > 0)
{
if (mode == kTextTruncateHead)
{
if (dir > 0)
{
for (auto i = distance; i > 0 && left != right; --i)
++left;
}
else
{
for (auto i = distance; i > 0 && left != text.begin (); --i)
--left;
}
truncatedText = "..";
}
else if (mode == kTextTruncateTail)
{
if (dir > 0)
{
for (auto i = distance; i > 0 && left != right; --i)
--right;
}
else
{
for (auto i = distance; i > 0 && right != text.end (); --i)
++right;
}
truncatedText = "";
}
truncatedText += {left.base (), right.base ()};
if (mode == kTextTruncateTail)
truncatedText += "..";
result = truncatedText;
width = painter->getStringWidth (nullptr, result.getPlatformString (), true);
width += textInset.x * 2;
if (left == right)
break;
}
dir *= -1;
}
if (left == right && flags & kReturnEmptyIfTruncationIsPlaceholderOnly)
result = "";
return result;
}
return text;
}
//------------------------------------------------------------------------
void drawIconAndText (CDrawContext* context, CBitmap* iconToDraw, IconPosition iconPosition,
CHoriTxtAlign textAlignment, CCoord textIconMargin, CRect drawRect,
const UTF8String& title, CFontRef font, CColor textColor,
TextTruncateMode textTruncateMode)
{
if (iconToDraw)
{
CRect iconRect (0, 0, iconToDraw->getWidth (), iconToDraw->getHeight ());
iconRect.offset (drawRect.left, drawRect.top);
switch (iconPosition)
{
case kIconLeft:
{
iconRect.offset (textIconMargin,
drawRect.getHeight () / 2. - iconRect.getHeight () / 2.);
drawRect.left = iconRect.right;
drawRect.right -= textIconMargin;
if (textAlignment == kLeftText)
drawRect.left += textIconMargin;
break;
}
case kIconRight:
{
iconRect.offset (drawRect.getWidth () - (textIconMargin + iconRect.getWidth ()),
drawRect.getHeight () / 2. - iconRect.getHeight () / 2.);
drawRect.right = iconRect.left;
drawRect.left += textIconMargin;
if (textAlignment == kRightText)
drawRect.right -= textIconMargin;
break;
}
case kIconCenterAbove:
{
iconRect.offset (drawRect.getWidth () / 2. - iconRect.getWidth () / 2., 0);
if (title.empty ())
iconRect.offset (0, drawRect.getHeight () / 2. - iconRect.getHeight () / 2.);
else
{
iconRect.offset (0, drawRect.getHeight () / 2. -
(iconRect.getHeight () / 2. +
(textIconMargin + font->getSize ()) / 2.));
drawRect.top = iconRect.bottom + textIconMargin;
drawRect.setHeight (font->getSize ());
if (textAlignment == kLeftText)
drawRect.left += textIconMargin;
else if (textAlignment == kRightText)
drawRect.right -= textIconMargin;
}
break;
}
case kIconCenterBelow:
{
iconRect.offset (drawRect.getWidth () / 2. - iconRect.getWidth () / 2., 0);
if (title.empty ())
iconRect.offset (0, drawRect.getHeight () / 2. - iconRect.getHeight () / 2.);
else
{
iconRect.offset (0, drawRect.getHeight () / 2. - (iconRect.getHeight () / 2.) +
(textIconMargin + font->getSize ()) / 2.);
drawRect.top = iconRect.top - (textIconMargin + font->getSize ());
drawRect.setHeight (font->getSize ());
if (textAlignment == kLeftText)
drawRect.left += textIconMargin;
else if (textAlignment == kRightText)
drawRect.right -= textIconMargin;
}
break;
}
}
context->drawBitmap (iconToDraw, iconRect);
}
else
{
if (textAlignment == kLeftText)
drawRect.left += textIconMargin;
else if (textAlignment == kRightText)
drawRect.right -= textIconMargin;
}
if (!title.empty ())
{
context->setFont (font);
context->setFontColor (textColor);
if (textTruncateMode != kTextTruncateNone)
{
UTF8String truncatedText =
createTruncatedText (textTruncateMode, title, font, drawRect.getWidth (),
CPoint (0, 0), kReturnEmptyIfTruncationIsPlaceholderOnly);
context->drawString (truncatedText.getPlatformString (), drawRect, textAlignment);
}
else
context->drawString (title.getPlatformString (), drawRect, textAlignment);
}
}
}
} // namespaces