dwrite: Partially implement newer TranslateColorGlyphRun() variant.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d967200938
commit
cb0b746f9a
|
@ -315,8 +315,9 @@ extern HRESULT get_local_refkey(const WCHAR*,const FILETIME*,void**,UINT32*) DEC
|
|||
extern HRESULT get_filestream_from_file(IDWriteFontFile*,IDWriteFontFileStream**) DECLSPEC_HIDDEN;
|
||||
extern BOOL is_face_type_supported(DWRITE_FONT_FACE_TYPE) DECLSPEC_HIDDEN;
|
||||
extern HRESULT get_family_names_from_stream(IDWriteFontFileStream*,UINT32,DWRITE_FONT_FACE_TYPE,IDWriteLocalizedStrings**) DECLSPEC_HIDDEN;
|
||||
extern HRESULT create_colorglyphenum(FLOAT,FLOAT,const DWRITE_GLYPH_RUN*,const DWRITE_GLYPH_RUN_DESCRIPTION*,DWRITE_MEASURING_MODE,
|
||||
const DWRITE_MATRIX*,UINT32,IDWriteColorGlyphRunEnumerator**) DECLSPEC_HIDDEN;
|
||||
extern HRESULT create_colorglyphenum(D2D1_POINT_2F origin, const DWRITE_GLYPH_RUN *run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS formats, DWRITE_MEASURING_MODE mode, const DWRITE_MATRIX *transform, UINT32 palette,
|
||||
IDWriteColorGlyphRunEnumerator1 **enumerator) DECLSPEC_HIDDEN;
|
||||
extern BOOL lb_is_newline_char(WCHAR) DECLSPEC_HIDDEN;
|
||||
extern HRESULT create_system_fontfallback(IDWriteFactory7 *factory, IDWriteFontFallback1 **fallback) DECLSPEC_HIDDEN;
|
||||
extern void release_system_fontfallback(IDWriteFontFallback1 *fallback) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -397,8 +397,7 @@ struct dwrite_colorglyphenum
|
|||
IDWriteColorGlyphRunEnumerator1 IDWriteColorGlyphRunEnumerator1_iface;
|
||||
LONG refcount;
|
||||
|
||||
FLOAT origin_x; /* original run origin */
|
||||
FLOAT origin_y;
|
||||
D2D1_POINT_2F origin; /* original run origin */
|
||||
|
||||
IDWriteFontFace5 *fontface; /* for convenience */
|
||||
DWRITE_COLOR_GLYPH_RUN1 colorrun; /* returned with GetCurrentRun() */
|
||||
|
@ -6431,8 +6430,8 @@ static BOOL colorglyphenum_build_color_run(struct dwrite_colorglyphenum *glyphen
|
|||
glyphenum->color_offsets[g] = glyphenum->offsets[g];
|
||||
}
|
||||
|
||||
colorrun->baselineOriginX = glyphenum->origin_x + get_glyph_origin(glyphenum, first_glyph);
|
||||
colorrun->baselineOriginY = glyphenum->origin_y;
|
||||
colorrun->baselineOriginX = glyphenum->origin.x + get_glyph_origin(glyphenum, first_glyph);
|
||||
colorrun->baselineOriginY = glyphenum->origin.y;
|
||||
colorrun->glyphRun.glyphCount = glyphenum->run.glyphCount;
|
||||
colorrun->paletteIndex = 0xffff;
|
||||
memset(&colorrun->runColor, 0, sizeof(colorrun->runColor));
|
||||
|
@ -6470,8 +6469,8 @@ static BOOL colorglyphenum_build_color_run(struct dwrite_colorglyphenum *glyphen
|
|||
glyphenum->palette, colorrun->paletteIndex, hr);
|
||||
}
|
||||
/* found a glyph position new color run starts from, origin is "original origin + distance to this glyph" */
|
||||
colorrun->baselineOriginX = glyphenum->origin_x + get_glyph_origin(glyphenum, g);
|
||||
colorrun->baselineOriginY = glyphenum->origin_y;
|
||||
colorrun->baselineOriginX = glyphenum->origin.x + get_glyph_origin(glyphenum, g);
|
||||
colorrun->baselineOriginY = glyphenum->origin.y;
|
||||
glyphenum->color_advances[index] = glyphenum->advances[g];
|
||||
got_palette_index = TRUE;
|
||||
}
|
||||
|
@ -6562,9 +6561,9 @@ static const IDWriteColorGlyphRunEnumerator1Vtbl colorglyphenumvtbl =
|
|||
colorglyphenum1_GetCurrentRun,
|
||||
};
|
||||
|
||||
HRESULT create_colorglyphenum(float originX, float originY, const DWRITE_GLYPH_RUN *run,
|
||||
const DWRITE_GLYPH_RUN_DESCRIPTION *rundescr, DWRITE_MEASURING_MODE measuring_mode,
|
||||
const DWRITE_MATRIX *transform, unsigned int palette, IDWriteColorGlyphRunEnumerator **ret)
|
||||
HRESULT create_colorglyphenum(D2D1_POINT_2F origin, const DWRITE_GLYPH_RUN *run,
|
||||
const DWRITE_GLYPH_RUN_DESCRIPTION *rundescr, DWRITE_GLYPH_IMAGE_FORMATS formats, DWRITE_MEASURING_MODE measuring_mode,
|
||||
const DWRITE_MATRIX *transform, unsigned int palette, IDWriteColorGlyphRunEnumerator1 **ret)
|
||||
{
|
||||
struct dwrite_colorglyphenum *colorglyphenum;
|
||||
BOOL colorfont, has_colored_glyph;
|
||||
|
@ -6580,13 +6579,28 @@ HRESULT create_colorglyphenum(float originX, float originY, const DWRITE_GLYPH_R
|
|||
if (!colorfont)
|
||||
return DWRITE_E_NOCOLOR;
|
||||
|
||||
if (!(formats & (DWRITE_GLYPH_IMAGE_FORMATS_COLR |
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_SVG |
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_PNG |
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_JPEG |
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_TIFF |
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8)))
|
||||
{
|
||||
return DWRITE_E_NOCOLOR;
|
||||
}
|
||||
|
||||
if (formats & ~(DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE | DWRITE_GLYPH_IMAGE_FORMATS_CFF | DWRITE_GLYPH_IMAGE_FORMATS_COLR))
|
||||
{
|
||||
FIXME("Unimplemented formats requested %#x.\n", formats);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
if (!(colorglyphenum = calloc(1, sizeof(*colorglyphenum))))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
colorglyphenum->IDWriteColorGlyphRunEnumerator1_iface.lpVtbl = &colorglyphenumvtbl;
|
||||
colorglyphenum->refcount = 1;
|
||||
colorglyphenum->origin_x = originX;
|
||||
colorglyphenum->origin_y = originY;
|
||||
colorglyphenum->origin = origin;
|
||||
colorglyphenum->fontface = &fontface->IDWriteFontFace5_iface;
|
||||
IDWriteFontFace5_AddRef(colorglyphenum->fontface);
|
||||
colorglyphenum->glyphs = NULL;
|
||||
|
@ -6648,7 +6662,7 @@ HRESULT create_colorglyphenum(float originX, float originY, const DWRITE_GLYPH_R
|
|||
run->fontEmSize, 1.0f, transform, run->glyphIndices[i], run->isSideways);
|
||||
}
|
||||
|
||||
*ret = (IDWriteColorGlyphRunEnumerator *)&colorglyphenum->IDWriteColorGlyphRunEnumerator1_iface;
|
||||
*ret = &colorglyphenum->IDWriteColorGlyphRunEnumerator1_iface;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -1398,13 +1398,17 @@ static HRESULT WINAPI dwritefactory2_CreateFontFallbackBuilder(IDWriteFactory7 *
|
|||
}
|
||||
|
||||
static HRESULT WINAPI dwritefactory2_TranslateColorGlyphRun(IDWriteFactory7 *iface, FLOAT originX, FLOAT originY,
|
||||
const DWRITE_GLYPH_RUN *run, const DWRITE_GLYPH_RUN_DESCRIPTION *rundescr, DWRITE_MEASURING_MODE mode,
|
||||
const DWRITE_MATRIX *transform, UINT32 palette, IDWriteColorGlyphRunEnumerator **colorlayers)
|
||||
const DWRITE_GLYPH_RUN *run, const DWRITE_GLYPH_RUN_DESCRIPTION *run_desc, DWRITE_MEASURING_MODE measuring_mode,
|
||||
const DWRITE_MATRIX *transform, UINT32 palette, IDWriteColorGlyphRunEnumerator **layers)
|
||||
{
|
||||
TRACE("%p, %.8e, %.8e, %p, %p, %d, %p, %u, %p.\n", iface, originX, originY, run, rundescr, mode,
|
||||
transform, palette, colorlayers);
|
||||
D2D1_POINT_2F origin = { originX, originY };
|
||||
|
||||
return create_colorglyphenum(originX, originY, run, rundescr, mode, transform, palette, colorlayers);
|
||||
TRACE("%p, %.8e, %.8e, %p, %p, %d, %p, %u, %p.\n", iface, originX, originY, run, run_desc, measuring_mode,
|
||||
transform, palette, layers);
|
||||
|
||||
return create_colorglyphenum(origin, run, run_desc, DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE
|
||||
| DWRITE_GLYPH_IMAGE_FORMATS_CFF | DWRITE_GLYPH_IMAGE_FORMATS_COLR,
|
||||
measuring_mode, transform, palette, (IDWriteColorGlyphRunEnumerator1 **)layers);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI dwritefactory2_CreateCustomRenderingParams(IDWriteFactory7 *iface, FLOAT gamma, FLOAT contrast,
|
||||
|
@ -1697,15 +1701,15 @@ static HRESULT WINAPI dwritefactory3_GetFontDownloadQueue(IDWriteFactory7 *iface
|
|||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI dwritefactory4_TranslateColorGlyphRun(IDWriteFactory7 *iface, D2D1_POINT_2F baseline_origin,
|
||||
static HRESULT WINAPI dwritefactory4_TranslateColorGlyphRun(IDWriteFactory7 *iface, D2D1_POINT_2F origin,
|
||||
DWRITE_GLYPH_RUN const *run, DWRITE_GLYPH_RUN_DESCRIPTION const *run_desc,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS desired_formats, DWRITE_MEASURING_MODE measuring_mode, DWRITE_MATRIX const *transform,
|
||||
UINT32 palette, IDWriteColorGlyphRunEnumerator1 **layers)
|
||||
{
|
||||
FIXME("%p, %p, %p, %u, %d, %p, %u, %p: stub\n", iface, run, run_desc, desired_formats, measuring_mode,
|
||||
transform, palette, layers);
|
||||
TRACE("%p, %.8e, %.8e, %p, %p, %u, %d, %p, %u, %p.\n", iface, origin.x, origin.y, run, run_desc, desired_formats,
|
||||
measuring_mode, transform, palette, layers);
|
||||
|
||||
return E_NOTIMPL;
|
||||
return create_colorglyphenum(origin, run, run_desc, desired_formats, measuring_mode, transform, palette, layers);
|
||||
}
|
||||
|
||||
HRESULT compute_glyph_origins(DWRITE_GLYPH_RUN const *run, DWRITE_MEASURING_MODE measuring_mode,
|
||||
|
|
|
@ -7671,6 +7671,7 @@ static void test_TranslateColorGlyphRun(void)
|
|||
const DWRITE_COLOR_GLYPH_RUN *colorrun;
|
||||
IDWriteFontFace2 *fontface2;
|
||||
IDWriteFontFace *fontface;
|
||||
IDWriteFactory4 *factory4;
|
||||
IDWriteFactory2 *factory;
|
||||
DWRITE_GLYPH_RUN run;
|
||||
UINT32 codepoints[2];
|
||||
|
@ -7740,7 +7741,8 @@ static void test_TranslateColorGlyphRun(void)
|
|||
win_skip("IDWriteColorGlyphRunEnumerator1 is not supported.\n");
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
for (;;)
|
||||
{
|
||||
hasrun = FALSE;
|
||||
hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &hasrun);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
@ -7749,22 +7751,24 @@ static void test_TranslateColorGlyphRun(void)
|
|||
break;
|
||||
|
||||
hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &colorrun);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(colorrun->glyphRun.fontFace != NULL, "got fontface %p\n", colorrun->glyphRun.fontFace);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
ok(colorrun->glyphRun.fontFace == fontface, "Unexpected fontface %p.\n", colorrun->glyphRun.fontFace);
|
||||
ok(colorrun->glyphRun.fontEmSize == 20.0f, "got wrong font size %f\n", colorrun->glyphRun.fontEmSize);
|
||||
ok(colorrun->glyphRun.glyphCount > 0, "got wrong glyph count %u\n", colorrun->glyphRun.glyphCount);
|
||||
ok(colorrun->glyphRun.glyphCount == 1, "Unexpected glyph count %u.\n", colorrun->glyphRun.glyphCount);
|
||||
ok(colorrun->glyphRun.glyphIndices != NULL, "got null glyph indices %p\n", colorrun->glyphRun.glyphIndices);
|
||||
ok(colorrun->glyphRun.glyphAdvances != NULL, "got null glyph advances %p\n", colorrun->glyphRun.glyphAdvances);
|
||||
ok(!colorrun->glyphRunDescription, "Unexpected description pointer.\n");
|
||||
|
||||
if (layers1)
|
||||
{
|
||||
hr = IDWriteColorGlyphRunEnumerator1_GetCurrentRun(layers1, &colorrun1);
|
||||
ok(hr == S_OK, "Failed to get color runt, hr %#x.\n", hr);
|
||||
ok(colorrun1->glyphRun.fontFace != NULL, "Unexpected fontface %p.\n", colorrun1->glyphRun.fontFace);
|
||||
ok(colorrun1->glyphRun.fontEmSize == 20.0f, "Unexpected font size %f.\n", colorrun1->glyphRun.fontEmSize);
|
||||
ok(colorrun1->glyphRun.glyphCount > 0, "Unexpected glyph count %u\n", colorrun1->glyphRun.glyphCount);
|
||||
ok(colorrun1->glyphRun.glyphIndices != NULL, "Unexpected indices array.\n");
|
||||
ok(colorrun1->glyphRun.glyphAdvances != NULL, "Unexpected advances array.\n");
|
||||
ok((const DWRITE_COLOR_GLYPH_RUN *)colorrun1 == colorrun, "Unexpected pointer.\n");
|
||||
ok(colorrun1->glyphImageFormat == (DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE | DWRITE_GLYPH_IMAGE_FORMATS_COLR) ||
|
||||
colorrun1->glyphImageFormat == DWRITE_GLYPH_IMAGE_FORMATS_NONE,
|
||||
"Unexpected glyph image format %#x.\n", colorrun1->glyphImageFormat);
|
||||
ok(colorrun1->measuringMode == DWRITE_MEASURING_MODE_NATURAL, "Unexpected measuring mode %d.\n",
|
||||
colorrun1->measuringMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7804,6 +7808,7 @@ static void test_TranslateColorGlyphRun(void)
|
|||
codepoints[0] = 'A';
|
||||
hr = IDWriteFontFace_GetGlyphIndices(fontface, codepoints, 1, glyphs);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(!!*glyphs, "Unexpected glyph.\n");
|
||||
|
||||
layers = (void*)0xdeadbeef;
|
||||
hr = IDWriteFactory2_TranslateColorGlyphRun(factory, 0.0f, 0.0f, &run, NULL,
|
||||
|
@ -7822,11 +7827,94 @@ static void test_TranslateColorGlyphRun(void)
|
|||
|
||||
layers = NULL;
|
||||
hr = IDWriteFactory2_TranslateColorGlyphRun(factory, 0.0f, 0.0f, &run, NULL,
|
||||
DWRITE_MEASURING_MODE_NATURAL, NULL, 0, &layers);
|
||||
DWRITE_MEASURING_MODE_NATURAL, NULL, 0, &layers);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(layers != NULL, "got %p\n", layers);
|
||||
|
||||
hr = IDWriteColorGlyphRunEnumerator_QueryInterface(layers, &IID_IDWriteColorGlyphRunEnumerator1, (void **)&layers1);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
hasrun = FALSE;
|
||||
hr = IDWriteColorGlyphRunEnumerator1_MoveNext(layers1, &hasrun);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
if (!hasrun)
|
||||
break;
|
||||
|
||||
hr = IDWriteColorGlyphRunEnumerator1_GetCurrentRun(layers1, &colorrun1);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
ok(!!colorrun1->glyphRun.fontFace, "Unexpected fontface %p.\n", colorrun1->glyphRun.fontFace);
|
||||
ok(colorrun1->glyphRun.fontEmSize == 20.0f, "got wrong font size %f\n", colorrun1->glyphRun.fontEmSize);
|
||||
ok(colorrun1->glyphRun.glyphCount > 0, "Unexpected glyph count %u.\n", colorrun1->glyphRun.glyphCount);
|
||||
ok(!!colorrun1->glyphRun.glyphIndices, "Unexpected indices %p.\n", colorrun1->glyphRun.glyphIndices);
|
||||
ok(!!colorrun1->glyphRun.glyphAdvances, "Unexpected advances %p.\n", colorrun1->glyphRun.glyphAdvances);
|
||||
ok(!colorrun1->glyphRunDescription, "Unexpected description pointer.\n");
|
||||
todo_wine
|
||||
ok(colorrun1->glyphImageFormat == (DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE | DWRITE_GLYPH_IMAGE_FORMATS_COLR) ||
|
||||
colorrun1->glyphImageFormat == DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE, "Unexpected glyph image format %#x.\n",
|
||||
colorrun1->glyphImageFormat);
|
||||
ok(colorrun1->measuringMode == DWRITE_MEASURING_MODE_NATURAL, "Unexpected measuring mode %d.\n",
|
||||
colorrun1->measuringMode);
|
||||
}
|
||||
|
||||
IDWriteColorGlyphRunEnumerator1_Release(layers1);
|
||||
}
|
||||
IDWriteColorGlyphRunEnumerator_Release(layers);
|
||||
|
||||
if (SUCCEEDED(IDWriteFactory2_QueryInterface(factory, &IID_IDWriteFactory4, (void **)&factory4)))
|
||||
{
|
||||
D2D1_POINT_2F origin;
|
||||
|
||||
origin.x = origin.y = 0.0f;
|
||||
hr = IDWriteFactory4_TranslateColorGlyphRun(factory4, origin, &run, NULL,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_NONE, DWRITE_MEASURING_MODE_NATURAL, NULL, 0, &layers1);
|
||||
ok(hr == DWRITE_E_NOCOLOR, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDWriteFactory4_TranslateColorGlyphRun(factory4, origin, &run, NULL,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE, DWRITE_MEASURING_MODE_NATURAL, NULL, 0, &layers1);
|
||||
ok(hr == DWRITE_E_NOCOLOR, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDWriteFactory4_TranslateColorGlyphRun(factory4, origin, &run, NULL,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_CFF, DWRITE_MEASURING_MODE_NATURAL, NULL, 0, &layers1);
|
||||
ok(hr == DWRITE_E_NOCOLOR, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IDWriteFactory4_TranslateColorGlyphRun(factory4, origin, &run, NULL,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_COLR, DWRITE_MEASURING_MODE_NATURAL, NULL, 0, &layers1);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
hasrun = FALSE;
|
||||
hr = IDWriteColorGlyphRunEnumerator1_MoveNext(layers1, &hasrun);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
if (!hasrun)
|
||||
break;
|
||||
|
||||
hr = IDWriteColorGlyphRunEnumerator1_GetCurrentRun(layers1, &colorrun1);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
ok(!!colorrun1->glyphRun.fontFace, "Unexpected fontface %p.\n", colorrun1->glyphRun.fontFace);
|
||||
ok(colorrun1->glyphRun.fontEmSize == 20.0f, "got wrong font size %f\n", colorrun1->glyphRun.fontEmSize);
|
||||
ok(colorrun1->glyphRun.glyphCount > 0, "Unexpected glyph count %u.\n", colorrun1->glyphRun.glyphCount);
|
||||
ok(!!colorrun1->glyphRun.glyphIndices, "Unexpected indices %p.\n", colorrun1->glyphRun.glyphIndices);
|
||||
ok(!!colorrun1->glyphRun.glyphAdvances, "Unexpected advances %p.\n", colorrun1->glyphRun.glyphAdvances);
|
||||
ok(!colorrun1->glyphRunDescription, "Unexpected description pointer.\n");
|
||||
ok(colorrun1->glyphImageFormat == DWRITE_GLYPH_IMAGE_FORMATS_COLR ||
|
||||
colorrun1->glyphImageFormat == DWRITE_GLYPH_IMAGE_FORMATS_NONE, "Unexpected glyph image format %#x.\n",
|
||||
colorrun1->glyphImageFormat);
|
||||
ok(colorrun1->measuringMode == DWRITE_MEASURING_MODE_NATURAL, "Unexpected measuring mode %d.\n",
|
||||
colorrun1->measuringMode);
|
||||
}
|
||||
|
||||
IDWriteColorGlyphRunEnumerator1_Release(layers1);
|
||||
|
||||
IDWriteFactory4_Release(factory4);
|
||||
}
|
||||
else
|
||||
win_skip("IDWriteFactory4::TranslateColorGlyphRun() is not supported.\n");
|
||||
|
||||
IDWriteFontFace2_Release(fontface2);
|
||||
IDWriteFontFace_Release(fontface);
|
||||
ref = IDWriteFactory2_Release(factory);
|
||||
|
|
Loading…
Reference in New Issue