mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 13:28:03 +02:00
Merge branch 'dwrite-font-variations' into 'master'
DWrite: Add support for font variations Closes #877 See merge request cairo/cairo!601
This commit is contained in:
commit
e2a52c0870
2 changed files with 144 additions and 42 deletions
|
|
@ -507,7 +507,7 @@ _cairo_dwrite_font_face_destroy (void *font_face)
|
|||
{
|
||||
cairo_dwrite_font_face_t *dwrite_font_face = static_cast<cairo_dwrite_font_face_t*>(font_face);
|
||||
if (dwrite_font_face->dwriteface)
|
||||
dwrite_font_face->dwriteface->Release();
|
||||
dwrite_font_face->dwriteface->Release();
|
||||
if (dwrite_font_face->rendering_params)
|
||||
dwrite_font_face->rendering_params->Release();
|
||||
return TRUE;
|
||||
|
|
@ -532,10 +532,8 @@ _cairo_dwrite_glyph_run_from_glyphs(cairo_glyph_t *glyphs,
|
|||
FLOAT *advances = const_cast<FLOAT*>(run->glyphAdvances);
|
||||
DWRITE_GLYPH_OFFSET *offsets = const_cast<DWRITE_GLYPH_OFFSET*>(run->glyphOffsets);
|
||||
|
||||
cairo_dwrite_font_face_t *dwriteff = reinterpret_cast<cairo_dwrite_font_face_t*>(scaled_font->base.font_face);
|
||||
|
||||
run->bidiLevel = 0;
|
||||
run->fontFace = dwriteff->dwriteface;
|
||||
run->fontFace = scaled_font->dwriteface;
|
||||
run->glyphCount = num_glyphs;
|
||||
run->isSideways = FALSE;
|
||||
|
||||
|
|
@ -628,6 +626,54 @@ do_grayscale(IDWriteFontFace *dwface, unsigned int ppem)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
set_dwrite_axes_from_string (const char *string,
|
||||
DWRITE_FONT_AXIS_VALUE *dwrite_axes,
|
||||
UINT32 count)
|
||||
{
|
||||
const char *p = string;
|
||||
|
||||
while (p && *p) {
|
||||
const char *start;
|
||||
const char *end, *end2;
|
||||
DWRITE_FONT_AXIS_TAG tag;
|
||||
double value;
|
||||
|
||||
while (_cairo_isspace (*p)) p++;
|
||||
|
||||
start = p;
|
||||
end = strchr (p, ',');
|
||||
if (end && (end - p < 6))
|
||||
goto skip;
|
||||
|
||||
tag = DWRITE_MAKE_FONT_AXIS_TAG (p[0], p[1], p[2], p[3]);
|
||||
|
||||
p += 4;
|
||||
while (_cairo_isspace (*p)) p++;
|
||||
if (*p == '=') p++;
|
||||
|
||||
if (p - start < 5)
|
||||
goto skip;
|
||||
|
||||
value = _cairo_strtod (p, (char **) &end2);
|
||||
|
||||
while (end2 && _cairo_isspace (*end2)) end2++;
|
||||
|
||||
if (end2 && (*end2 != ',' && *end2 != '\0'))
|
||||
goto skip;
|
||||
|
||||
for (UINT32 i = 0; i < count; i++) {
|
||||
if (dwrite_axes[i].axisTag == tag) {
|
||||
dwrite_axes[i].value = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
skip:
|
||||
p = end ? end + 1 : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_dwrite_font_face_scaled_font_create (void *abstract_face,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
|
|
@ -656,6 +702,60 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face,
|
|||
return status;
|
||||
}
|
||||
|
||||
if (options->variations) {
|
||||
RefPtr<IDWriteFontFace5> dwriteface5;
|
||||
|
||||
/* Since Windows 10 20348 */
|
||||
if (SUCCEEDED (font_face->dwriteface->QueryInterface(&dwriteface5))) {
|
||||
RefPtr<IDWriteFontResource> dwritefontresource;
|
||||
|
||||
if (dwriteface5->HasVariations () &&
|
||||
SUCCEEDED (dwriteface5->GetFontResource (&dwritefontresource)))
|
||||
{
|
||||
UINT32 count = MIN (dwriteface5->GetFontAxisValueCount (), 500);
|
||||
DWRITE_FONT_AXIS_VALUE *dwrite_axes = new DWRITE_FONT_AXIS_VALUE[count];
|
||||
UINT32 variables_count = 0;
|
||||
|
||||
/* Sort variable axes first */
|
||||
for (UINT32 i = 0; i < count; i++) {
|
||||
if (dwritefontresource->GetFontAxisAttributes (i) & DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE) {
|
||||
if (variables_count != i) {
|
||||
DWRITE_FONT_AXIS_VALUE swap_aux = dwrite_axes[variables_count];
|
||||
dwrite_axes[variables_count] = dwrite_axes[i];
|
||||
dwrite_axes[i] = swap_aux;
|
||||
}
|
||||
|
||||
variables_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED (dwriteface5->GetFontAxisValues(dwrite_axes, count))) {
|
||||
RefPtr<IDWriteFontFace5> dwriteface_new5;
|
||||
|
||||
set_dwrite_axes_from_string (options->variations, dwrite_axes, variables_count);
|
||||
|
||||
/* Can't use constexpr with mingw-w64 headers */
|
||||
const DWRITE_FONT_SIMULATIONS all_simulations = DWRITE_FONT_SIMULATIONS_BOLD |
|
||||
DWRITE_FONT_SIMULATIONS_OBLIQUE;
|
||||
if (SUCCEEDED (dwritefontresource->CreateFontFace(all_simulations,
|
||||
dwrite_axes,
|
||||
count,
|
||||
&dwriteface_new5)))
|
||||
{
|
||||
dwrite_font->dwriteface = dwriteface_new5.forget().drop();
|
||||
}
|
||||
}
|
||||
|
||||
delete[] dwrite_axes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!dwrite_font->dwriteface) {
|
||||
font_face->dwriteface->AddRef ();
|
||||
dwrite_font->dwriteface = font_face->dwriteface;
|
||||
}
|
||||
|
||||
dwrite_font->mat = dwrite_font->base.ctm;
|
||||
cairo_matrix_multiply(&dwrite_font->mat, &dwrite_font->mat, font_matrix);
|
||||
dwrite_font->mat_inverse = dwrite_font->mat;
|
||||
|
|
@ -667,9 +767,9 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face,
|
|||
if (dwrite_font->measuring_mode == DWRITE_MEASURING_MODE_GDI_CLASSIC ||
|
||||
dwrite_font->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL) {
|
||||
DWRITE_MATRIX transform = _cairo_dwrite_matrix_from_matrix (&dwrite_font->mat);
|
||||
font_face->dwriteface->GetGdiCompatibleMetrics(1, 1, &transform, &metrics);
|
||||
dwrite_font->dwriteface->GetGdiCompatibleMetrics(1, 1, &transform, &metrics);
|
||||
} else {
|
||||
font_face->dwriteface->GetMetrics(&metrics);
|
||||
dwrite_font->dwriteface->GetMetrics(&metrics);
|
||||
}
|
||||
|
||||
extents.ascent = (FLOAT)metrics.ascent / metrics.designUnitsPerEm;
|
||||
|
|
@ -698,7 +798,7 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face,
|
|||
}
|
||||
|
||||
if (default_quality == CAIRO_ANTIALIAS_GRAY) {
|
||||
if (!do_grayscale(font_face->dwriteface, (unsigned int)_cairo_round(font_matrix->yy))) {
|
||||
if (!do_grayscale(dwrite_font->dwriteface, (unsigned int)_cairo_round(font_matrix->yy))) {
|
||||
default_quality = CAIRO_ANTIALIAS_NONE;
|
||||
}
|
||||
}
|
||||
|
|
@ -720,6 +820,9 @@ static void
|
|||
_cairo_dwrite_scaled_font_fini(void *scaled_font)
|
||||
{
|
||||
cairo_dwrite_scaled_font_t *dwrite_font = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
|
||||
|
||||
dwrite_font->dwriteface->Release ();
|
||||
|
||||
if (dwrite_font->rendering_params)
|
||||
dwrite_font->rendering_params->Release();
|
||||
}
|
||||
|
|
@ -765,10 +868,9 @@ _cairo_dwrite_ucs4_to_index(void *scaled_font,
|
|||
uint32_t ucs4)
|
||||
{
|
||||
cairo_dwrite_scaled_font_t *dwritesf = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
|
||||
cairo_dwrite_font_face_t *face = reinterpret_cast<cairo_dwrite_font_face_t*>(dwritesf->base.font_face);
|
||||
UINT16 index = 0;
|
||||
|
||||
UINT16 index;
|
||||
face->dwriteface->GetGlyphIndicesA(&ucs4, 1, &index);
|
||||
dwritesf->dwriteface->GetGlyphIndicesA(&ucs4, 1, &index);
|
||||
return index;
|
||||
}
|
||||
|
||||
|
|
@ -787,12 +889,12 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_
|
|||
if (font_face->measuring_mode == DWRITE_MEASURING_MODE_GDI_CLASSIC ||
|
||||
font_face->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL) {
|
||||
DWRITE_MATRIX transform = _cairo_dwrite_matrix_from_matrix (&scaled_font->mat);
|
||||
font_face->dwriteface->GetGdiCompatibleMetrics(1, 1, &transform, &fontMetrics);
|
||||
scaled_font->dwriteface->GetGdiCompatibleMetrics(1, 1, &transform, &fontMetrics);
|
||||
BOOL natural = font_face->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL;
|
||||
hr = font_face->dwriteface->GetGdiCompatibleGlyphMetrics (1, 1, &transform, natural, &charIndex, 1, &metrics, FALSE);
|
||||
hr = scaled_font->dwriteface->GetGdiCompatibleGlyphMetrics (1, 1, &transform, natural, &charIndex, 1, &metrics, FALSE);
|
||||
} else {
|
||||
font_face->dwriteface->GetMetrics(&fontMetrics);
|
||||
hr = font_face->dwriteface->GetDesignGlyphMetrics(&charIndex, 1, &metrics);
|
||||
scaled_font->dwriteface->GetMetrics(&fontMetrics);
|
||||
hr = scaled_font->dwriteface->GetDesignGlyphMetrics(&charIndex, 1, &metrics);
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
|
@ -972,16 +1074,15 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon
|
|||
offset.ascenderOffset = 0;
|
||||
UINT16 glyphId = (UINT16)_cairo_scaled_glyph_index(scaled_glyph);
|
||||
FLOAT advance = 0.0;
|
||||
cairo_dwrite_font_face_t *dwriteff = (cairo_dwrite_font_face_t*)scaled_font->base.font_face;
|
||||
|
||||
HRESULT hr = dwriteff->dwriteface->GetGlyphRunOutline(1,
|
||||
&glyphId,
|
||||
&advance,
|
||||
&offset,
|
||||
1,
|
||||
FALSE,
|
||||
FALSE,
|
||||
&recorder);
|
||||
HRESULT hr = scaled_font->dwriteface->GetGlyphRunOutline(1,
|
||||
&glyphId,
|
||||
&advance,
|
||||
&offset,
|
||||
1,
|
||||
FALSE,
|
||||
FALSE,
|
||||
&recorder);
|
||||
if (!SUCCEEDED(hr))
|
||||
return _cairo_dwrite_error (hr, "GetGlyphRunOutline failed");
|
||||
|
||||
|
|
@ -1039,7 +1140,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
|
|||
/* Y-axis is inverted */
|
||||
offset.ascenderOffset = -(FLOAT)y;
|
||||
|
||||
run.fontFace = dwrite_font_face->dwriteface;
|
||||
run.fontFace = scaled_font->dwriteface;
|
||||
run.fontEmSize = 1;
|
||||
run.glyphCount = 1;
|
||||
run.glyphIndices = &index;
|
||||
|
|
@ -1061,7 +1162,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
|
|||
|
||||
RefPtr<IDWriteFontFace2> fontFace2;
|
||||
UINT32 palette_count = 0;
|
||||
if (SUCCEEDED(dwrite_font_face->dwriteface->QueryInterface(&fontFace2)))
|
||||
if (SUCCEEDED(scaled_font->dwriteface->QueryInterface(&fontFace2)))
|
||||
palette_count = fontFace2->GetColorPaletteCount();
|
||||
|
||||
UINT32 palette_index = CAIRO_COLOR_PALETTE_DEFAULT;
|
||||
|
|
@ -1287,7 +1388,7 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_
|
|||
|
||||
run.glyphCount = 1;
|
||||
run.glyphAdvances = &advance;
|
||||
run.fontFace = ((cairo_dwrite_font_face_t*)scaled_font->base.font_face)->dwriteface;
|
||||
run.fontFace = scaled_font->dwriteface;
|
||||
run.fontEmSize = 1.0f;
|
||||
run.bidiLevel = 0;
|
||||
run.glyphIndices = &index;
|
||||
|
|
@ -1327,18 +1428,17 @@ _cairo_dwrite_load_truetype_table(void *scaled_font,
|
|||
unsigned long *length)
|
||||
{
|
||||
cairo_dwrite_scaled_font_t *dwritesf = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
|
||||
cairo_dwrite_font_face_t *face = reinterpret_cast<cairo_dwrite_font_face_t*>(dwritesf->base.font_face);
|
||||
|
||||
const void *data;
|
||||
UINT32 size;
|
||||
void *tableContext;
|
||||
BOOL exists;
|
||||
HRESULT hr;
|
||||
hr = face->dwriteface->TryGetFontTable (be32_to_cpu (tag),
|
||||
&data,
|
||||
&size,
|
||||
&tableContext,
|
||||
&exists);
|
||||
hr = dwritesf->dwriteface->TryGetFontTable (be32_to_cpu (tag),
|
||||
&data,
|
||||
&size,
|
||||
&tableContext,
|
||||
&exists);
|
||||
if (FAILED(hr))
|
||||
return _cairo_dwrite_error (hr, "TryGetFontTable failed");
|
||||
|
||||
|
|
@ -1353,7 +1453,7 @@ _cairo_dwrite_load_truetype_table(void *scaled_font,
|
|||
*length = size;
|
||||
|
||||
if (tableContext) {
|
||||
face->dwriteface->ReleaseFontTable(tableContext);
|
||||
dwritesf->dwriteface->ReleaseFontTable(tableContext);
|
||||
}
|
||||
return (cairo_int_status_t)CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -1363,17 +1463,16 @@ _cairo_dwrite_is_synthetic(void *scaled_font,
|
|||
cairo_bool_t *is_synthetic)
|
||||
{
|
||||
cairo_dwrite_scaled_font_t *dwritesf = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
|
||||
cairo_dwrite_font_face_t *face = reinterpret_cast<cairo_dwrite_font_face_t*>(dwritesf->base.font_face);
|
||||
HRESULT hr;
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (face->dwriteface->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
|
||||
if (dwritesf->dwriteface->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
|
||||
*is_synthetic = FALSE;
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
RefPtr<IDWriteFontFace5> fontFace5;
|
||||
if (FAILED(face->dwriteface->QueryInterface(&fontFace5))) {
|
||||
if (FAILED(dwritesf->dwriteface->QueryInterface(&fontFace5))) {
|
||||
/* If IDWriteFontFace5 is not available, assume this version of
|
||||
* DirectWrite does not support variations.
|
||||
*/
|
||||
|
|
@ -1825,10 +1924,10 @@ compare_font_tables (cairo_dwrite_font_face_t *dwface,
|
|||
HRESULT hr;
|
||||
|
||||
hr = dwface->dwriteface->TryGetFontTable(be32_to_cpu (tag),
|
||||
&dw_data,
|
||||
&dw_size,
|
||||
&dw_tableContext,
|
||||
&dw_exists);
|
||||
&dw_data,
|
||||
&dw_size,
|
||||
&dw_tableContext,
|
||||
&dw_exists);
|
||||
if (FAILED(hr))
|
||||
return _cairo_dwrite_error (hr, "TryGetFontTable failed");
|
||||
|
||||
|
|
@ -1864,7 +1963,7 @@ compare_font_tables (cairo_dwrite_font_face_t *dwface,
|
|||
cleanup:
|
||||
free (buffer);
|
||||
if (dw_tableContext)
|
||||
dwface->dwriteface->ReleaseFontTable(dw_tableContext);
|
||||
dwface->dwriteface->ReleaseFontTable(dw_tableContext);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
@ -1929,6 +2028,8 @@ _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_
|
|||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* TODO: use scaled font? */
|
||||
|
||||
LOGFONTW logfont;
|
||||
if (FAILED(gdiInterop->ConvertFontFaceToLOGFONT (dwface->dwriteface, &logfont))) {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
|
|
|||
|
|
@ -68,7 +68,8 @@ struct _cairo_dwrite_scaled_font {
|
|||
cairo_matrix_t mat;
|
||||
cairo_matrix_t mat_inverse;
|
||||
cairo_antialias_t antialias_mode;
|
||||
IDWriteRenderingParams *rendering_params;
|
||||
IDWriteFontFace *dwriteface; /* Can't use RefPtr because this struct is malloc'd. */
|
||||
IDWriteRenderingParams *rendering_params; /* Can't use RefPtr because this struct is malloc'd. */
|
||||
DWRITE_MEASURING_MODE measuring_mode;
|
||||
};
|
||||
typedef struct _cairo_dwrite_scaled_font cairo_dwrite_scaled_font_t;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue