Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions IGraphics/Controls/IAttributedTextControl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
==============================================================================

This file is part of the iPlug 2 library. Copyright (C) the iPlug 2 developers.

See LICENSE.txt for more info.

==============================================================================
*/

#pragma once

/**
* @file
* @copydoc IAboutBoxControl
*/

#include "IControl.h"

BEGIN_IPLUG_NAMESPACE
BEGIN_IGRAPHICS_NAMESPACE

/* An IControl for drawing attributed text to a layer using the native text routines, e.g. CoreGraphics */

class IAttributedTextControl : public IEditableTextControl
{
public:
IAttributedTextControl(const IRECT& bounds, const char* str, const IText& text = DEFAULT_TEXT)
: IEditableTextControl(bounds, str, text)
{
}

int DrawAttributedText(IGraphics& g, const char* str, const IRECT& textArea, const IText& text)
{
auto* vg = static_cast<NVGcontext*>(g.GetDrawContext());

float w, h;
auto imageData = g.DrawAttributedText(str, text, w, h);
int imgID = nvgCreateImageRGBA(vg, ceil(w * g.GetTotalScale()), ceil(h * g.GetTotalScale()), 0, imageData.Get());

float x, y;

switch (text.mAlign)
{
case EAlign::Near:
x = textArea.L;
break;
case EAlign::Center:
x = textArea.MW() - (w / 2.0);
break;
case EAlign::Far:
x = textArea.R;
break;
}

switch (text.mVAlign)
{
case EVAlign::Top:
y = textArea.T;
break;
case EVAlign::Middle:
y = textArea.MH() - (h / 2.0);
break;
case EVAlign::Bottom:
y = textArea.B - h;
break;
}

nvgBeginPath(vg);
nvgRect(vg, x, y, w, h);
NVGpaint imgPaint = nvgImagePattern(vg, x, y, w, h, 0, imgID, 1.f);
nvgFillPaint(vg, imgPaint);
nvgFill(vg);

// Clean up
// nvgDeleteImage(vg, imgID);

return imgID;
}

void Draw(IGraphics& g) override
{
int imgID = -1;
if (!g.CheckLayer(mLayer))
{
g.StartLayer(this, mRECT);
imgID = DrawAttributedText(g, mStr.Get(), mRECT.GetPadded(-10.f), mText);
mLayer = g.EndLayer();
}

g.DrawLayer(mLayer, &mBlend);

if (imgID > -1)
{
auto* vg = static_cast<NVGcontext*>(g.GetDrawContext());
nvgDeleteImage(vg, imgID);
}
}

void OnRescale() override
{
if (mLayer)
mLayer->Invalidate();
}

void OnResize() override
{
if (mLayer)
mLayer->Invalidate();
}

void SetStr(const char* str) override
{
ITextControl::SetStr(str);
mLayer->Invalidate();
}
private:
ILayerPtr mLayer;
};


END_IGRAPHICS_NAMESPACE
END_IPLUG_NAMESPACE
8 changes: 8 additions & 0 deletions IGraphics/IGraphics.h
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,14 @@ class IGraphics
/** Get the app group ID on macOS and iOS, returns emtpy string on other OSs */
virtual const char* GetAppGroupID() const { return ""; }

/** Draw text to a bitmap. May be used to render colour emojis etc. using platform text rendering
* @param str UTF8 encoded string to render
* @param text The IText style for the text
* @param width The width of the drawn text in pixels, without any draw or screen scaling applied
* @param height The height of the drawn text in pixels, without any draw or screen scaling applied
* @return Bitmap data containing the rendered text */
virtual RawBitmapData DrawAttributedText(const char* str, const IText& text, float& width, float& height) { return RawBitmapData(); }

protected:
/* Activate the context for the view (GL only) */
virtual void ActivateGLContext() {};
Expand Down
1 change: 1 addition & 0 deletions IGraphics/Platforms/IGraphicsIOS.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class IGraphicsIOS final : public IGRAPHICS_DRAW_CLASS

EUIAppearance GetUIAppearance() const override;

RawBitmapData DrawAttributedText(const char* str, const IText& text, float& width, float& height) override;
protected:
PlatformFontPtr LoadPlatformFont(const char* fontID, const char* fileNameOrResID) override;
PlatformFontPtr LoadPlatformFont(const char* fontID, const char* fontName, ETextStyle style) override;
Expand Down
55 changes: 55 additions & 0 deletions IGraphics/Platforms/IGraphicsIOS.mm
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,61 @@ float GetScaleForScreen(int plugWidth, int plugHeight)
}
}

RawBitmapData IGraphicsIOS::DrawAttributedText(const char* str, const IText& text, float& width, float& height)
{
auto scaleFactor = GetTotalScale();
CFStringRef string = CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8);
CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringReplaceString(attrString, CFRangeMake(0, 0), string);
CFRelease(string);

CFStringRef fontName = CFStringCreateWithCString(NULL, text.mFont, kCFStringEncodingUTF8);
CoreTextFontDescriptor* CTFontDescriptor = CoreTextHelpers::GetCTFontDescriptor(text, sFontDescriptorCache);
double ratio = CTFontDescriptor->GetEMRatio()/* * GetDrawScale()*/;
CTFontRef font = CTFontCreateWithName(fontName, text.mSize * ratio, NULL);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = {text.mFGColor.R / 255.0, text.mFGColor.G / 255.0, text.mFGColor.B / 255.0, text.mFGColor.A / 255.0}; // RGBA
CGColorRef color = CGColorCreate(colorSpace, components);
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, CFAttributedStringGetLength(attrString)), kCTFontAttributeName, font);
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, CFAttributedStringGetLength(attrString)), kCTForegroundColorAttributeName, color);
CFRelease(color);
CGColorSpaceRelease(colorSpace);
CFRelease(font);
CFRelease(fontName);

CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);
CGSize textSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, CFAttributedStringGetLength(attrString)), NULL, CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX), NULL);

CGMutablePathRef path = CGPathCreateMutable();
CGRect bounds = CGRectMake(0, 0, textSize.width, textSize.height); // Create bounds according to the text size
CGPathAddRect(path, NULL, bounds);

CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, CFAttributedStringGetLength(attrString)), path, NULL);

CFRelease(framesetter);
CFRelease(attrString);

width = textSize.width;
height = textSize.height;
int bitmapWidth = ceil(width * scaleFactor);
int bitmapHeight = ceil(height * scaleFactor);

RawBitmapData imageData;
imageData.Resize(4 * bitmapWidth * bitmapHeight);
imageData.SetToZero();
CGContextRef bitmapContext = CGBitmapContextCreate(imageData.Get(), bitmapWidth, bitmapHeight, 8, bitmapWidth * 4, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedLast);
CGContextScaleCTM(bitmapContext, scaleFactor, scaleFactor);
CTFrameDraw(frame, bitmapContext);
CGContextFlush(bitmapContext);

CFRelease(frame);
CGPathRelease(path);
CGContextRelease(bitmapContext);

return imageData;
}


#if defined IGRAPHICS_NANOVG
#include "IGraphicsNanoVG.cpp"
#elif defined IGRAPHICS_SKIA
Expand Down
3 changes: 3 additions & 0 deletions IGraphics/Platforms/IGraphicsMac.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ class IGraphicsMac final : public IGRAPHICS_DRAW_CLASS
float MeasureText(const IText& text, const char* str, IRECT& bounds) const override;

EUIAppearance GetUIAppearance() const override;

RawBitmapData DrawAttributedText(const char* str, const IText& text, float& width, float& height) override;

protected:

IPopupMenu* CreatePlatformPopupMenu(IPopupMenu& menu, const IRECT bounds, bool& isAsync) override;
Expand Down
54 changes: 54 additions & 0 deletions IGraphics/Platforms/IGraphicsMac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,60 @@ static int GetSystemVersion()
return EUIAppearance::Light;
}

RawBitmapData IGraphicsMac::DrawAttributedText(const char* str, const IText& text, float& width, float& height)
{
auto scaleFactor = GetTotalScale();
CFStringRef string = CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8);
CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringReplaceString(attrString, CFRangeMake(0, 0), string);
CFRelease(string);

CFStringRef fontName = CFStringCreateWithCString(NULL, text.mFont, kCFStringEncodingUTF8);
CoreTextFontDescriptor* CTFontDescriptor = CoreTextHelpers::GetCTFontDescriptor(text, sFontDescriptorCache);
double ratio = CTFontDescriptor->GetEMRatio()/* * GetDrawScale()*/;
CTFontRef font = CTFontCreateWithName(fontName, text.mSize * ratio, NULL);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = {text.mFGColor.R / 255.0, text.mFGColor.G / 255.0, text.mFGColor.B / 255.0, text.mFGColor.A / 255.0}; // RGBA
CGColorRef color = CGColorCreate(colorSpace, components);
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, CFAttributedStringGetLength(attrString)), kCTFontAttributeName, font);
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, CFAttributedStringGetLength(attrString)), kCTForegroundColorAttributeName, color);
CFRelease(color);
CGColorSpaceRelease(colorSpace);
CFRelease(font);
CFRelease(fontName);

CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);
CGSize textSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, CFAttributedStringGetLength(attrString)), NULL, CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX), NULL);

CGMutablePathRef path = CGPathCreateMutable();
CGRect bounds = CGRectMake(0, 0, textSize.width, textSize.height); // Create bounds according to the text size
CGPathAddRect(path, NULL, bounds);

CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, CFAttributedStringGetLength(attrString)), path, NULL);

CFRelease(framesetter);
CFRelease(attrString);

width = textSize.width;
height = textSize.height;
int bitmapWidth = ceil(width * scaleFactor);
int bitmapHeight = ceil(height * scaleFactor);

RawBitmapData imageData;
imageData.Resize(4 * bitmapWidth * bitmapHeight);
imageData.SetToZero();
CGContextRef bitmapContext = CGBitmapContextCreate(imageData.Get(), bitmapWidth, bitmapHeight, 8, bitmapWidth * 4, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedLast);
CGContextScaleCTM(bitmapContext, scaleFactor, scaleFactor);
CTFrameDraw(frame, bitmapContext);
CGContextFlush(bitmapContext);

CFRelease(frame);
CGPathRelease(path);
CGContextRelease(bitmapContext);

return imageData;
}

void IGraphicsMac::ActivateGLContext()
{
#ifdef IGRAPHICS_GL
Expand Down