mirror of
https://github.com/reactos/wine.git
synced 2024-11-28 22:20:26 +00:00
dwrite: Initial GetGlyphRunOutline() implementation.
This commit is contained in:
parent
88202b3d9b
commit
17a24679b4
@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include "dwrite_2.h"
|
||||
#include "d2d1.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
@ -125,12 +126,30 @@ extern HRESULT opentype_get_font_strings_from_id(const void*,DWRITE_INFORMATIONA
|
||||
extern HRESULT bidi_computelevels(const WCHAR*,UINT32,UINT8,UINT8*,UINT8*) DECLSPEC_HIDDEN;
|
||||
extern WCHAR bidi_get_mirrored_char(WCHAR) DECLSPEC_HIDDEN;
|
||||
|
||||
enum outline_point_tag {
|
||||
OUTLINE_POINT_START = 1 << 0,
|
||||
OUTLINE_POINT_END = 1 << 1,
|
||||
OUTLINE_POINT_BEZIER = 1 << 2,
|
||||
OUTLINE_POINT_LINE = 1 << 3
|
||||
};
|
||||
|
||||
struct glyph_outline {
|
||||
D2D1_POINT_2F *points;
|
||||
UINT8 *tags;
|
||||
UINT16 count;
|
||||
FLOAT advance;
|
||||
};
|
||||
|
||||
extern HRESULT new_glyph_outline(UINT32,struct glyph_outline**) DECLSPEC_HIDDEN;
|
||||
extern void free_glyph_outline(struct glyph_outline*) DECLSPEC_HIDDEN;
|
||||
|
||||
/* FreeType integration */
|
||||
extern BOOL init_freetype(void) DECLSPEC_HIDDEN;
|
||||
extern void release_freetype(void) DECLSPEC_HIDDEN;
|
||||
extern HRESULT freetype_get_design_glyph_metrics(IDWriteFontFace2*,UINT16,UINT16,DWRITE_GLYPH_METRICS*) DECLSPEC_HIDDEN;
|
||||
extern void freetype_notify_cacheremove(IDWriteFontFace2*) DECLSPEC_HIDDEN;
|
||||
extern BOOL freetype_is_monospaced(IDWriteFontFace2*) DECLSPEC_HIDDEN;
|
||||
extern HRESULT freetype_get_glyph_outline(IDWriteFontFace2*,FLOAT,UINT16,struct glyph_outline**) DECLSPEC_HIDDEN;
|
||||
|
||||
/* Glyph shaping */
|
||||
enum SCRIPT_JUSTIFY
|
||||
|
@ -421,14 +421,127 @@ static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace2 *iface, void
|
||||
IDWriteFontFileStream_ReleaseFileFragment(This->streams[0], table_context);
|
||||
}
|
||||
|
||||
HRESULT new_glyph_outline(UINT32 count, struct glyph_outline **ret)
|
||||
{
|
||||
struct glyph_outline *outline;
|
||||
D2D1_POINT_2F *points;
|
||||
UINT8 *tags;
|
||||
|
||||
*ret = NULL;
|
||||
|
||||
outline = heap_alloc(sizeof(*outline));
|
||||
if (!outline)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
points = heap_alloc(count*sizeof(D2D1_POINT_2F));
|
||||
tags = heap_alloc(count*sizeof(UINT8));
|
||||
if (!points || !tags) {
|
||||
heap_free(points);
|
||||
heap_free(tags);
|
||||
heap_free(outline);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
outline->points = points;
|
||||
outline->tags = tags;
|
||||
outline->count = count;
|
||||
outline->advance = 0.0;
|
||||
|
||||
*ret = outline;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void free_glyph_outline(struct glyph_outline *outline)
|
||||
{
|
||||
heap_free(outline->points);
|
||||
heap_free(outline->tags);
|
||||
heap_free(outline);
|
||||
}
|
||||
|
||||
static void report_glyph_outline(const struct glyph_outline *outline, IDWriteGeometrySink *sink)
|
||||
{
|
||||
UINT16 p;
|
||||
|
||||
for (p = 0; p < outline->count; p++) {
|
||||
if (outline->tags[p] & OUTLINE_POINT_START) {
|
||||
ID2D1SimplifiedGeometrySink_BeginFigure(sink, outline->points[p], D2D1_FIGURE_BEGIN_FILLED);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (outline->tags[p] & OUTLINE_POINT_LINE)
|
||||
ID2D1SimplifiedGeometrySink_AddLines(sink, outline->points+p, 1);
|
||||
else if (outline->tags[p] & OUTLINE_POINT_BEZIER) {
|
||||
static const UINT16 segment_length = 3;
|
||||
ID2D1SimplifiedGeometrySink_AddBeziers(sink, (D2D1_BEZIER_SEGMENT*)&outline->points[p], 1);
|
||||
p += segment_length - 1;
|
||||
}
|
||||
|
||||
if (outline->tags[p] & OUTLINE_POINT_END)
|
||||
ID2D1SimplifiedGeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void translate_glyph_outline(struct glyph_outline *outline, FLOAT xoffset, FLOAT yoffset)
|
||||
{
|
||||
UINT16 p;
|
||||
|
||||
for (p = 0; p < outline->count; p++) {
|
||||
outline->points[p].x += xoffset;
|
||||
outline->points[p].y += yoffset;
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace2 *iface, FLOAT emSize,
|
||||
UINT16 const *glyph_indices, FLOAT const* glyph_advances, DWRITE_GLYPH_OFFSET const *glyph_offsets,
|
||||
UINT32 glyph_count, BOOL is_sideways, BOOL is_rtl, IDWriteGeometrySink *geometrysink)
|
||||
UINT16 const *glyphs, FLOAT const* advances, DWRITE_GLYPH_OFFSET const *offsets,
|
||||
UINT32 count, BOOL is_sideways, BOOL is_rtl, IDWriteGeometrySink *sink)
|
||||
{
|
||||
struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
|
||||
FIXME("(%p)->(%f %p %p %p %u %d %d %p): stub\n", This, emSize, glyph_indices, glyph_advances, glyph_offsets,
|
||||
glyph_count, is_sideways, is_rtl, geometrysink);
|
||||
return E_NOTIMPL;
|
||||
FLOAT advance = 0.0;
|
||||
HRESULT hr;
|
||||
UINT32 g;
|
||||
|
||||
TRACE("(%p)->(%.2f %p %p %p %u %d %d %p)\n", This, emSize, glyphs, advances, offsets,
|
||||
count, is_sideways, is_rtl, sink);
|
||||
|
||||
if (!glyphs || !sink)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (is_sideways)
|
||||
FIXME("sideways mode is not supported.\n");
|
||||
|
||||
for (g = 0; g < count; g++) {
|
||||
FLOAT xoffset = 0.0, yoffset = 0.0;
|
||||
struct glyph_outline *outline;
|
||||
|
||||
/* FIXME: cache outlines */
|
||||
|
||||
hr = freetype_get_glyph_outline(iface, emSize, glyphs[g], &outline);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
/* glyph offsets act as current glyph adjustment */
|
||||
if (offsets) {
|
||||
xoffset += is_rtl ? -offsets[g].advanceOffset : offsets[g].advanceOffset;
|
||||
yoffset -= offsets[g].ascenderOffset;
|
||||
}
|
||||
|
||||
if (g == 0)
|
||||
advance = is_rtl ? -outline->advance : 0.0;
|
||||
|
||||
xoffset += advance;
|
||||
translate_glyph_outline(outline, xoffset, yoffset);
|
||||
|
||||
/* update advance to next glyph */
|
||||
if (advances)
|
||||
advance += is_rtl ? -advances[g] : advances[g];
|
||||
else
|
||||
advance += is_rtl ? -outline->advance : outline->advance;
|
||||
|
||||
report_glyph_outline(outline, sink);
|
||||
free_glyph_outline(outline);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace2 *iface, FLOAT emSize,
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <ft2build.h>
|
||||
#include FT_CACHE_H
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_OUTLINE_H
|
||||
#endif /* HAVE_FT2BUILD_H */
|
||||
|
||||
#include "windef.h"
|
||||
@ -65,6 +66,7 @@ MAKE_FUNCPTR(FT_Init_FreeType);
|
||||
MAKE_FUNCPTR(FT_Library_Version);
|
||||
MAKE_FUNCPTR(FT_Load_Glyph);
|
||||
MAKE_FUNCPTR(FT_New_Memory_Face);
|
||||
MAKE_FUNCPTR(FT_Outline_Transform);
|
||||
MAKE_FUNCPTR(FTC_Manager_New);
|
||||
MAKE_FUNCPTR(FTC_Manager_Done);
|
||||
MAKE_FUNCPTR(FTC_Manager_LookupFace);
|
||||
@ -134,6 +136,7 @@ BOOL init_freetype(void)
|
||||
LOAD_FUNCPTR(FT_Library_Version)
|
||||
LOAD_FUNCPTR(FT_Load_Glyph)
|
||||
LOAD_FUNCPTR(FT_New_Memory_Face)
|
||||
LOAD_FUNCPTR(FT_Outline_Transform)
|
||||
LOAD_FUNCPTR(FTC_Manager_New)
|
||||
LOAD_FUNCPTR(FTC_Manager_Done)
|
||||
LOAD_FUNCPTR(FTC_Manager_LookupFace)
|
||||
@ -225,6 +228,153 @@ BOOL freetype_is_monospaced(IDWriteFontFace2 *fontface)
|
||||
return is_monospaced;
|
||||
}
|
||||
|
||||
static inline void ft_vector_to_d2d_point(const FT_Vector *v, D2D1_POINT_2F *p)
|
||||
{
|
||||
p->x = v->x / 64.0;
|
||||
p->y = v->y / 64.0;
|
||||
}
|
||||
|
||||
static HRESULT get_outline_data(const FT_Outline *outline, struct glyph_outline **ret)
|
||||
{
|
||||
short i, j, contour = 0;
|
||||
D2D1_POINT_2F *points;
|
||||
UINT16 count = 0;
|
||||
UINT8 *tags;
|
||||
HRESULT hr;
|
||||
|
||||
/* we need all curves in cubic format */
|
||||
for (i = 0; i < outline->n_points; i++) {
|
||||
/* control point */
|
||||
if (!(outline->tags[i] & FT_Curve_Tag_On)) {
|
||||
if (!(outline->tags[i] & FT_Curve_Tag_Cubic)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
hr = new_glyph_outline(count, ret);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
points = (*ret)->points;
|
||||
tags = (*ret)->tags;
|
||||
|
||||
ft_vector_to_d2d_point(outline->points, points);
|
||||
tags[0] = OUTLINE_POINT_START;
|
||||
|
||||
for (i = 1, j = 1; i < outline->n_points; i++, j++) {
|
||||
/* mark start of new contour */
|
||||
if (tags[j-1] & OUTLINE_POINT_END)
|
||||
tags[j] = OUTLINE_POINT_START;
|
||||
else
|
||||
tags[j] = 0;
|
||||
|
||||
if (outline->tags[i] & FT_Curve_Tag_On) {
|
||||
ft_vector_to_d2d_point(outline->points+i, points+j);
|
||||
tags[j] |= OUTLINE_POINT_LINE;
|
||||
}
|
||||
else {
|
||||
/* third order curve */
|
||||
if (outline->tags[i] & FT_Curve_Tag_Cubic) {
|
||||
/* store 3 points, advance 3 points */
|
||||
|
||||
ft_vector_to_d2d_point(outline->points+i, points+j);
|
||||
ft_vector_to_d2d_point(outline->points+i+1, points+j+1);
|
||||
ft_vector_to_d2d_point(outline->points+i+2, points+j+2);
|
||||
|
||||
i += 2;
|
||||
}
|
||||
else {
|
||||
FT_Vector vec;
|
||||
|
||||
/* Convert the quadratic Beziers to cubic Beziers.
|
||||
The parametric eqn for a cubic Bezier is, from PLRM:
|
||||
r(t) = at^3 + bt^2 + ct + r0
|
||||
with the control points:
|
||||
r1 = r0 + c/3
|
||||
r2 = r1 + (c + b)/3
|
||||
r3 = r0 + c + b + a
|
||||
|
||||
A quadratic Bezier has the form:
|
||||
p(t) = (1-t)^2 p0 + 2(1-t)t p1 + t^2 p2
|
||||
|
||||
So equating powers of t leads to:
|
||||
r1 = 2/3 p1 + 1/3 p0
|
||||
r2 = 2/3 p1 + 1/3 p2
|
||||
and of course r0 = p0, r3 = p2
|
||||
*/
|
||||
|
||||
/* r1 */
|
||||
vec.x = 2 * outline->points[i].x + outline->points[i-1].x;
|
||||
vec.y = 2 * outline->points[i].y + outline->points[i-1].y;
|
||||
ft_vector_to_d2d_point(&vec, points+j);
|
||||
points[j].x /= 3.0;
|
||||
points[j].y /= 3.0;
|
||||
|
||||
/* r2 */
|
||||
vec.x = 2 * outline->points[i].x + outline->points[i+1].x;
|
||||
vec.y = 2 * outline->points[i].y + outline->points[i+1].y;
|
||||
ft_vector_to_d2d_point(&vec, points+j+1);
|
||||
points[j+1].x /= 3.0;
|
||||
points[j+1].y /= 3.0;
|
||||
|
||||
/* r3 */
|
||||
ft_vector_to_d2d_point(outline->points+i+1, points+j+2);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
tags[j] = tags[j+1] = tags[j+2] = OUTLINE_POINT_BEZIER;
|
||||
j += 2;
|
||||
}
|
||||
|
||||
/* mark end point */
|
||||
if (i < outline->n_points && outline->contours[contour] == i) {
|
||||
tags[j] |= OUTLINE_POINT_END;
|
||||
contour++;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT freetype_get_glyph_outline(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 index, struct glyph_outline **ret)
|
||||
{
|
||||
FTC_ScalerRec scaler;
|
||||
HRESULT hr = S_OK;
|
||||
FT_Size size;
|
||||
|
||||
scaler.face_id = fontface;
|
||||
scaler.width = emSize;
|
||||
scaler.height = emSize;
|
||||
scaler.pixel = 1;
|
||||
scaler.x_res = 0;
|
||||
scaler.y_res = 0;
|
||||
|
||||
EnterCriticalSection(&freetype_cs);
|
||||
if (pFTC_Manager_LookupSize(cache_manager, &scaler, &size) == 0) {
|
||||
if (pFT_Load_Glyph(size->face, index, FT_LOAD_DEFAULT) == 0) {
|
||||
FT_Outline *outline = &size->face->glyph->outline;
|
||||
FT_Matrix m;
|
||||
|
||||
m.xx = 1.0 * 0x10000;
|
||||
m.xy = 0;
|
||||
m.yx = 0;
|
||||
m.yy = -1.0 * 0x10000; /* flip Y axis */
|
||||
|
||||
pFT_Outline_Transform(outline, &m);
|
||||
|
||||
hr = get_outline_data(outline, ret);
|
||||
if (hr == S_OK)
|
||||
(*ret)->advance = size->face->glyph->metrics.horiAdvance >> 6;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&freetype_cs);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
#else /* HAVE_FREETYPE */
|
||||
|
||||
BOOL init_freetype(void)
|
||||
@ -250,4 +400,10 @@ BOOL freetype_is_monospaced(IDWriteFontFace2 *fontface)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HRESULT freetype_get_glyph_outline(IDWriteFontFace2 *fontface, FLOAT emSize, UINT16 index, struct glyph_outline **ret)
|
||||
{
|
||||
*ret = NULL;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
#endif /* HAVE_FREETYPE */
|
||||
|
@ -23,6 +23,8 @@
|
||||
|
||||
#include "windows.h"
|
||||
#include "dwrite_1.h"
|
||||
#include "initguid.h"
|
||||
#include "d2d1.h"
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
@ -378,6 +380,86 @@ static const struct IDWriteFontFileLoaderVtbl resourcefontfileloadervtbl = {
|
||||
|
||||
static IDWriteFontFileLoader rloader = { &resourcefontfileloadervtbl };
|
||||
|
||||
static D2D1_POINT_2F g_startpoints[2];
|
||||
static int g_startpoint_count;
|
||||
|
||||
static HRESULT WINAPI test_geometrysink_QueryInterface(ID2D1SimplifiedGeometrySink *iface, REFIID riid, void **ret)
|
||||
{
|
||||
if (IsEqualIID(riid, &IID_ID2D1SimplifiedGeometrySink) ||
|
||||
IsEqualIID(riid, &IID_IUnknown))
|
||||
{
|
||||
*ret = iface;
|
||||
ID2D1SimplifiedGeometrySink_AddRef(iface);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*ret = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG WINAPI test_geometrysink_AddRef(ID2D1SimplifiedGeometrySink *iface)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
static ULONG WINAPI test_geometrysink_Release(ID2D1SimplifiedGeometrySink *iface)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void WINAPI test_geometrysink_SetFillMode(ID2D1SimplifiedGeometrySink *iface, D2D1_FILL_MODE mode)
|
||||
{
|
||||
ok(mode == D2D1_FILL_MODE_WINDING, "fill mode %d\n", mode);
|
||||
}
|
||||
|
||||
static void WINAPI test_geometrysink_SetSegmentFlags(ID2D1SimplifiedGeometrySink *iface, D2D1_PATH_SEGMENT flags)
|
||||
{
|
||||
ok(0, "unexpected SetSegmentFlags() - flags %d\n", flags);
|
||||
}
|
||||
|
||||
static void WINAPI test_geometrysink_BeginFigure(ID2D1SimplifiedGeometrySink *iface,
|
||||
D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin)
|
||||
{
|
||||
ok(figureBegin == D2D1_FIGURE_BEGIN_FILLED, "begin figure %d\n", figureBegin);
|
||||
g_startpoints[g_startpoint_count++] = startPoint;
|
||||
}
|
||||
|
||||
static void WINAPI test_geometrysink_AddLines(ID2D1SimplifiedGeometrySink *iface,
|
||||
const D2D1_POINT_2F *points, UINT32 count)
|
||||
{
|
||||
}
|
||||
|
||||
static void WINAPI test_geometrysink_AddBeziers(ID2D1SimplifiedGeometrySink *iface,
|
||||
const D2D1_BEZIER_SEGMENT *beziers, UINT32 count)
|
||||
{
|
||||
}
|
||||
|
||||
static void WINAPI test_geometrysink_EndFigure(ID2D1SimplifiedGeometrySink *iface, D2D1_FIGURE_END figureEnd)
|
||||
{
|
||||
ok(figureEnd == D2D1_FIGURE_END_CLOSED, "end figure %d\n", figureEnd);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI test_geometrysink_Close(ID2D1SimplifiedGeometrySink *iface)
|
||||
{
|
||||
ok(0, "unexpected Close()\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static const ID2D1SimplifiedGeometrySinkVtbl test_geometrysink_vtbl = {
|
||||
test_geometrysink_QueryInterface,
|
||||
test_geometrysink_AddRef,
|
||||
test_geometrysink_Release,
|
||||
test_geometrysink_SetFillMode,
|
||||
test_geometrysink_SetSegmentFlags,
|
||||
test_geometrysink_BeginFigure,
|
||||
test_geometrysink_AddLines,
|
||||
test_geometrysink_AddBeziers,
|
||||
test_geometrysink_EndFigure,
|
||||
test_geometrysink_Close
|
||||
};
|
||||
|
||||
static ID2D1SimplifiedGeometrySink test_geomsink = { &test_geometrysink_vtbl };
|
||||
|
||||
static void test_CreateFontFromLOGFONT(void)
|
||||
{
|
||||
static const WCHAR tahomaspW[] = {'T','a','h','o','m','a',' ',0};
|
||||
@ -2740,6 +2822,112 @@ static void test_GetDesignGlyphAdvances(void)
|
||||
DeleteFileW(test_fontfile);
|
||||
}
|
||||
|
||||
static void test_GetGlyphRunOutline(void)
|
||||
{
|
||||
DWRITE_GLYPH_OFFSET offsets[2];
|
||||
IDWriteFactory *factory;
|
||||
IDWriteFontFile *file;
|
||||
IDWriteFontFace *face;
|
||||
UINT32 codepoint;
|
||||
FLOAT advances[2];
|
||||
UINT16 glyphs[2];
|
||||
HRESULT hr;
|
||||
|
||||
create_testfontfile(test_fontfile);
|
||||
factory = create_factory();
|
||||
|
||||
hr = IDWriteFactory_CreateFontFileReference(factory, test_fontfile, NULL, &file);
|
||||
ok(hr == S_OK, "got 0x%08x\n",hr);
|
||||
|
||||
hr = IDWriteFactory_CreateFontFace(factory, DWRITE_FONT_FACE_TYPE_TRUETYPE, 1, &file, 0, DWRITE_FONT_SIMULATIONS_NONE, &face);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
IDWriteFontFile_Release(file);
|
||||
|
||||
codepoint = 'A';
|
||||
glyphs[0] = 0;
|
||||
hr = IDWriteFontFace_GetGlyphIndices(face, &codepoint, 1, glyphs);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(glyphs[0] > 0, "got %u\n", glyphs[0]);
|
||||
glyphs[1] = glyphs[0];
|
||||
|
||||
hr = IDWriteFontFace_GetGlyphRunOutline(face, 2048.0, glyphs, advances, offsets, 1, FALSE, FALSE, NULL);
|
||||
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
|
||||
|
||||
hr = IDWriteFontFace_GetGlyphRunOutline(face, 2048.0, NULL, NULL, offsets, 1, FALSE, FALSE, &test_geomsink);
|
||||
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
|
||||
|
||||
advances[0] = 1.0;
|
||||
advances[1] = 0.0;
|
||||
|
||||
offsets[0].advanceOffset = 1.0;
|
||||
offsets[0].ascenderOffset = 1.0;
|
||||
offsets[1].advanceOffset = 0.0;
|
||||
offsets[1].ascenderOffset = 0.0;
|
||||
|
||||
/* default advances, no offsets */
|
||||
memset(g_startpoints, 0, sizeof(g_startpoints));
|
||||
g_startpoint_count = 0;
|
||||
hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, NULL, 2, FALSE, FALSE, &test_geomsink);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(g_startpoint_count == 2, "got %d\n", g_startpoint_count);
|
||||
if (g_startpoint_count == 2) {
|
||||
/* glyph advance of 500 is applied */
|
||||
ok(g_startpoints[0].x == 229.5 && g_startpoints[0].y == -629.0, "0: got (%.2f,%.2f)\n", g_startpoints[0].x, g_startpoints[0].y);
|
||||
ok(g_startpoints[1].x == 729.5 && g_startpoints[1].y == -629.0, "1: got (%.2f,%.2f)\n", g_startpoints[1].x, g_startpoints[1].y);
|
||||
}
|
||||
|
||||
/* default advances, no offsets, RTL */
|
||||
memset(g_startpoints, 0, sizeof(g_startpoints));
|
||||
g_startpoint_count = 0;
|
||||
hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, NULL, 2, FALSE, TRUE, &test_geomsink);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(g_startpoint_count == 2, "got %d\n", g_startpoint_count);
|
||||
if (g_startpoint_count == 2) {
|
||||
/* advance is -500 now */
|
||||
ok(g_startpoints[0].x == -270.5 && g_startpoints[0].y == -629.0, "0: got (%.2f,%.2f)\n", g_startpoints[0].x, g_startpoints[0].y);
|
||||
ok(g_startpoints[1].x == -770.5 && g_startpoints[1].y == -629.0, "1: got (%.2f,%.2f)\n", g_startpoints[1].x, g_startpoints[1].y);
|
||||
}
|
||||
|
||||
/* default advances, additional offsets */
|
||||
memset(g_startpoints, 0, sizeof(g_startpoints));
|
||||
g_startpoint_count = 0;
|
||||
hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, offsets, 2, FALSE, FALSE, &test_geomsink);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(g_startpoint_count == 2, "got %d\n", g_startpoint_count);
|
||||
if (g_startpoint_count == 2) {
|
||||
/* offsets applied to first contour */
|
||||
ok(g_startpoints[0].x == 230.5 && g_startpoints[0].y == -630.0, "0: got (%.2f,%.2f)\n", g_startpoints[0].x, g_startpoints[0].y);
|
||||
ok(g_startpoints[1].x == 729.5 && g_startpoints[1].y == -629.0, "1: got (%.2f,%.2f)\n", g_startpoints[1].x, g_startpoints[1].y);
|
||||
}
|
||||
|
||||
/* default advances, additional offsets, RTL */
|
||||
memset(g_startpoints, 0, sizeof(g_startpoints));
|
||||
g_startpoint_count = 0;
|
||||
hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, NULL, offsets, 2, FALSE, TRUE, &test_geomsink);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(g_startpoint_count == 2, "got %d\n", g_startpoint_count);
|
||||
if (g_startpoint_count == 2) {
|
||||
ok(g_startpoints[0].x == -271.5 && g_startpoints[0].y == -630.0, "0: got (%.2f,%.2f)\n", g_startpoints[0].x, g_startpoints[0].y);
|
||||
ok(g_startpoints[1].x == -770.5 && g_startpoints[1].y == -629.0, "1: got (%.2f,%.2f)\n", g_startpoints[1].x, g_startpoints[1].y);
|
||||
}
|
||||
|
||||
/* custom advances and offsets, offset turns total advance value to zero */
|
||||
memset(g_startpoints, 0, sizeof(g_startpoints));
|
||||
g_startpoint_count = 0;
|
||||
hr = IDWriteFontFace_GetGlyphRunOutline(face, 1024.0, glyphs, advances, offsets, 2, FALSE, FALSE, &test_geomsink);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(g_startpoint_count == 2, "got %d\n", g_startpoint_count);
|
||||
if (g_startpoint_count == 2) {
|
||||
ok(g_startpoints[0].x == 230.5 && g_startpoints[0].y == -630.0, "0: got (%.2f,%.2f)\n", g_startpoints[0].x, g_startpoints[0].y);
|
||||
ok(g_startpoints[1].x == 230.5 && g_startpoints[1].y == -629.0, "1: got (%.2f,%.2f)\n", g_startpoints[1].x, g_startpoints[1].y);
|
||||
}
|
||||
|
||||
IDWriteFontFace_Release(face);
|
||||
IDWriteFactory_Release(factory);
|
||||
|
||||
DeleteFileW(test_fontfile);
|
||||
}
|
||||
|
||||
START_TEST(font)
|
||||
{
|
||||
IDWriteFactory *factory;
|
||||
@ -2776,6 +2964,7 @@ START_TEST(font)
|
||||
test_GetDesignGlyphMetrics();
|
||||
test_GetDesignGlyphAdvances();
|
||||
test_IsMonospacedFont();
|
||||
test_GetGlyphRunOutline();
|
||||
|
||||
IDWriteFactory_Release(factory);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user