GDI - 我可以使用新的Windows 10 Segoe UI Emoji彩色字体和DrawText吗?

Jea*_*ond 6 winapi gdi colors emoji

我正在使用Embarcadero RAD Studio(10.2东京启动器)和Windows GDI创建一个c ++项目,通过DrawText()函数绘制文本.

我最近看到Windows 10提供了一种新的"Segoe UI Emoji"字体,它可能允许文本功能绘制彩色表情符号.我发现了几个使用Direct2D的例子,但没有一个使用纯GDI函数.

我也尝试了一个简单的代码,如下所示:

HDC hDC = ::GetDC(Handle);

std::auto_ptr<TCanvas> pCanvas(new TCanvas());
pCanvas->Handle = hDC;

pCanvas->Brush->Color = clWhite;
pCanvas->Brush->Style = bsSolid;
pCanvas->FillRect(TRect(0, 0, ClientWidth, ClientHeight));

const std::wstring text = L"Test        ";

TRect textRect(10, 10, ClientWidth - 10, ClientHeight - 10);

hFont = ::CreateFont(-40,
                      0, 
                      0,
                      0,
                      FW_DONTCARE,
                      FALSE,
                      FALSE,
                      FALSE,
                      DEFAULT_CHARSET,
                      OUT_OUTLINE_PRECIS,
                      CLIP_DEFAULT_PRECIS,
                      CLEARTYPE_QUALITY,
                      VARIABLE_PITCH,
                      L"Segoe UI Emoji");

::SelectObject(hDC, hFont);

::DrawTextW(hDC,
            text.c_str(),
            text.length(),
            &textRect,
            DT_LEFT | DT_TOP | DT_SINGLELINE);

::DeleteObject(hFont);
Run Code Online (Sandbox Code Playgroud)

输出结果在符号方面听起来不错,但它们以黑白绘制,没有颜色,如下面的屏幕截图所示: 在此输入图像描述

我找不到任何其他选项可能允许使用彩色符号而不是黑白绘制文本.有没有办法在GDI DrawText()函数中激活颜色的支持,如果是的话,怎么做?或者只有Direct2D可以绘制彩色表情符号?

于2017年10月30日编辑

由于GDI无法完成这项工作(不幸的是,正如我所想),我在这里发布了上述代码的Direct2D版本,这对我有用.

const std::wstring text = L"Test        ";

HDC hDC = ::GetDC(Handle);

std::auto_ptr<TCanvas> pGDICanvas(new TCanvas());
pGDICanvas->Handle = hDC;

pGDICanvas->Brush->Color = clWhite;
pGDICanvas->Brush->Style = bsSolid;
pGDICanvas->FillRect(TRect(0, 0, ClientWidth, ClientHeight));

::D2D1_RECT_F textRect;
textRect.left   = 10;
textRect.top    = 10;
textRect.right  = ClientWidth  - 10;
textRect.bottom = ClientHeight - 10;

std::auto_ptr<TDirect2DCanvas> pCanvas(new TDirect2DCanvas(hDC, TRect(0, 0, ClientWidth, ClientHeight)));

// configure Direct2D font
pCanvas->Font->Size        = 40;
pCanvas->Font->Name        = L"Segoe UI Emoji";
pCanvas->Font->Orientation = 0;
pCanvas->Font->Pitch       = System::Uitypes::TFontPitch::fpVariable;
pCanvas->Font->Style       = TFontStyles();

// get DirectWrite text format object
_di_IDWriteTextFormat pFormat = pCanvas->Font->Handle;

if (!pFormat)
    return;

pCanvas->RenderTarget->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);

::D2D1_COLOR_F color;
color.r = 0.0f;
color.g = 0.0f;
color.b = 0.0f;
color.a = 1.0f;

::ID2D1SolidColorBrush* pBrush = NULL;

// create solid color brush, use pen color if rect is completely filled with outline
pCanvas->RenderTarget->CreateSolidColorBrush(color, &pBrush);

if (!pBrush)
    return;

// set horiz alignment
pFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);

// set vert alignment
pFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR);

// set reading direction
pFormat->SetReadingDirection(DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);

// set word wrapping mode
pFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);

IDWriteInlineObject* pInlineObject = NULL;

::DWRITE_TRIMMING trimming;
trimming.delimiter      = 0;
trimming.delimiterCount = 0;
trimming.granularity    = DWRITE_TRIMMING_GRANULARITY_NONE;

// set text trimming
pFormat->SetTrimming(&trimming, pInlineObject);

pCanvas->BeginDraw();

pCanvas->RenderTarget->DrawText(text.c_str(), text.length(), pFormat, textRect, pBrush,
            D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT);

pCanvas->EndDraw();
Run Code Online (Sandbox Code Playgroud)

当然,此代码仅在当前最新版本的Windows 10及更高版本上绘制彩色表情符号.在以前的版本中,文本将如上绘制(并且代码可能无法编译).

Sor*_*tir 6

GDI 不支持彩色字体(即使你走完整的 Uniscribe 路线),如果你想要彩色字体支持,你必须使用 Direct2D。更简单的 GDI API 不支持彩色字体是有道理的,因为彩色字体需要使用 OpenType 标签,而且 DrawText/TextOut 都没有提供这种级别的控制,Uniscribe 允许此类标签,但只是没有扩展以支持彩色字体。