Skip to content

Instantly share code, notes, and snippets.

@ebraminio
Created February 20, 2020 13:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ebraminio/e2d18feea65adaaeff6d6e041b7a3161 to your computer and use it in GitHub Desktop.
Save ebraminio/e2d18feea65adaaeff6d6e041b7a3161 to your computer and use it in GitHub Desktop.
Test GetGlyphRunOutline
// gcc -DHB_NO_MT c.cc -ldwrite && a.exe
// But it gives some apparently random number...
// M0,0 C0,0 0,-536870912 0,0 C0,0 -1610612736,0 0,0 L0,0 L0,0 C1073741824...
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <windows.h>
#include <DWrite_1.h>
#include <d2d1.h>
// Borrowed from NativeFontResourceDWrite.cpp of Mozilla but only load one font
class DWriteFontFileLoader : public IDWriteFontFileLoader
{
private:
IDWriteFontFileStream *mFontFileStream;
public:
DWriteFontFileLoader(IDWriteFontFileStream *fontFileStream)
{ mFontFileStream = fontFileStream; }
// IUnknown interface
IFACEMETHOD(QueryInterface) (IID const &iid, OUT void **ppObject)
{ return S_OK; }
IFACEMETHOD_(ULONG, AddRef) () { return 1; }
IFACEMETHOD_(ULONG, Release)() { return 1; }
// IDWriteFontFileLoader methods
virtual HRESULT STDMETHODCALLTYPE
CreateStreamFromKey(void const *fontFileReferenceKey,
uint32_t fontFileReferenceKeySize,
OUT IDWriteFontFileStream **fontFileStream)
{
*fontFileStream = mFontFileStream;
return S_OK;
}
};
class DWriteFontFileStream : public IDWriteFontFileStream
{
private:
uint8_t *mData;
uint32_t mSize;
public:
DWriteFontFileStream(uint8_t *aData, uint32_t aSize)
{
mData = aData;
mSize = aSize;
}
// IUnknown interface
IFACEMETHOD(QueryInterface) (IID const &iid, OUT void **ppObject)
{ return S_OK; }
IFACEMETHOD_(ULONG, AddRef) () { return 1; }
IFACEMETHOD_(ULONG, Release)() { return 1; }
// IDWriteFontFileStream methods
virtual HRESULT STDMETHODCALLTYPE
ReadFileFragment(void const **fragmentStart,
UINT64 fileOffset,
UINT64 fragmentSize,
OUT void **fragmentContext)
{
// We are required to do bounds checking.
if (fileOffset + fragmentSize > mSize)
return E_FAIL;
// truncate the 64 bit fileOffset to size_t sized index into mData
size_t index = static_cast<size_t>(fileOffset);
// We should be alive for the duration of this.
*fragmentStart = &mData[index];
*fragmentContext = nullptr;
return S_OK;
}
virtual void STDMETHODCALLTYPE
ReleaseFileFragment(void *fragmentContext) {}
virtual HRESULT STDMETHODCALLTYPE
GetFileSize(OUT UINT64 *fileSize)
{
*fileSize = mSize;
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE
GetLastWriteTime(OUT UINT64 *lastWriteTime) { return E_NOTIMPL; }
};
class GeometrySink : public IDWriteGeometrySink
{
public:
// IUnknown interface
IFACEMETHOD(QueryInterface) (IID const &iid, OUT void **ppObject)
{ return S_OK; }
IFACEMETHOD_(ULONG, AddRef) () { return 1; }
IFACEMETHOD_(ULONG, Release)() { return 1; }
GeometrySink() {}
void STDMETHODCALLTYPE AddBeziers(_In_ const D2D1_BEZIER_SEGMENT *beziers, unsigned int beziersCount)
{
for (unsigned i = 0; i < beziersCount; ++i)
printf("C%d,%d %d,%d %d,%d ", beziers[i].point1.x, beziers[i].point1.y,
beziers[i].point2.x, beziers[i].point2.y, beziers[i].point3.x, beziers[i].point3.y);
}
void STDMETHODCALLTYPE AddLines(_In_ const D2D1_POINT_2F *points, unsigned int pointsCount)
{
for (unsigned i = 0; i < pointsCount; ++i)
printf("L%d,%d ", points[i].x, points[i].y);
}
void STDMETHODCALLTYPE BeginFigure(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin)
{
printf("M%d,%d ", startPoint.x, startPoint.y);
}
void STDMETHODCALLTYPE EndFigure(D2D1_FIGURE_END figureEnd)
{
printf("Z");
}
HRESULT STDMETHODCALLTYPE Close()
{
return S_OK;
}
void STDMETHODCALLTYPE SetFillMode(D2D1_FILL_MODE fillMode)
{
// Interesting! Maybe we should one also
}
void STDMETHODCALLTYPE SetSegmentFlags(D2D1_PATH_SEGMENT vertexFlags)
{
}
};
int main()
{
FILE *f = fopen("c:\\windows\\Fonts\\tahoma.ttf", "rb");
fseek(f, 0, SEEK_END);
unsigned file_size = ftell(f);
rewind(f);
void *file_data = malloc(file_size);
fread(file_data, 1, file_size, f);
fclose(f);
IDWriteFactory *dwriteFactory;
DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
(IUnknown **)&dwriteFactory);
HRESULT hr;
DWriteFontFileStream *fontFileStream = new DWriteFontFileStream((uint8_t *)file_data, file_size);
DWriteFontFileLoader *fontFileLoader = new DWriteFontFileLoader(fontFileStream);
dwriteFactory->RegisterFontFileLoader(fontFileLoader);
IDWriteFontFile *fontFile;
uint64_t fontFileKey = 0;
dwriteFactory->CreateCustomFontFileReference(&fontFileKey, sizeof(fontFileKey),
fontFileLoader, &fontFile);
BOOL isSupported;
DWRITE_FONT_FILE_TYPE fileType;
DWRITE_FONT_FACE_TYPE faceType;
uint32_t numberOfFaces;
hr = fontFile->Analyze(&isSupported, &fileType, &faceType, &numberOfFaces);
IDWriteFontFace *fontFace;
dwriteFactory->CreateFontFace(faceType, 1, &fontFile, 0,
DWRITE_FONT_SIMULATIONS_NONE, &fontFace);
uint16_t a = 12;
IDWriteGeometrySink *sink = new GeometrySink();
fontFace->GetGlyphRunOutline(128, &a, 0, 0, 1, false, false, sink);
delete sink;
delete fontFileStream;
delete fontFileLoader;
free (file_data);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment