mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 02:58:02 +02:00
Merge branch 'issue-641-glyph-bounds' into 'master'
DWrite: clipped glyphs in win32 compositor Closes #641 See merge request cairo/cairo!459
This commit is contained in:
commit
b7d8da7d1f
1 changed files with 31 additions and 99 deletions
|
|
@ -1535,8 +1535,15 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
|
|||
*/
|
||||
rt->SetPixelsPerDip(1.0);
|
||||
|
||||
float x = 0, y = 0;
|
||||
if (transform) {
|
||||
rt->SetCurrentTransform(transform);
|
||||
DWRITE_MATRIX matrix = *transform;
|
||||
matrix.dx -= area.left;
|
||||
matrix.dy -= area.top;
|
||||
rt->SetCurrentTransform(&matrix);
|
||||
} else {
|
||||
x = (float) -area.left;
|
||||
y = (float) -area.top;
|
||||
}
|
||||
BitBlt(rt->GetMemoryDC(),
|
||||
0, 0,
|
||||
|
|
@ -1544,7 +1551,7 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
|
|||
surface->dc,
|
||||
area.left, area.top,
|
||||
SRCCOPY | NOMIRRORBITMAP);
|
||||
rt->DrawGlyphRun(0, 0, scaled_font->measuring_mode, run, params, color);
|
||||
rt->DrawGlyphRun(x, y, scaled_font->measuring_mode, run, params, color);
|
||||
BitBlt(surface->dc,
|
||||
area.left, area.top,
|
||||
area.right - area.left, area.bottom - area.top,
|
||||
|
|
@ -1580,6 +1587,7 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
|
|||
if (FAILED(hr))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
float x = 0, y = 0;
|
||||
if (transform) {
|
||||
rt->SetTransform(D2D1::Matrix3x2F(transform->m11,
|
||||
transform->m12,
|
||||
|
|
@ -1651,96 +1659,7 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface,
|
|||
DWRITE_GLYPH_OFFSET *offsets = const_cast<DWRITE_GLYPH_OFFSET*>(run.glyphOffsets);
|
||||
|
||||
BOOL transform = FALSE;
|
||||
/* Needed to calculate bounding box for efficient blitting */
|
||||
INT32 smallestX = INT_MAX;
|
||||
INT32 largestX = 0;
|
||||
INT32 smallestY = INT_MAX;
|
||||
INT32 largestY = 0;
|
||||
for (int i = 0; i < num_glyphs; i++) {
|
||||
if (glyphs[i].x < smallestX) {
|
||||
smallestX = (INT32)glyphs[i].x;
|
||||
}
|
||||
if (glyphs[i].x > largestX) {
|
||||
largestX = (INT32)glyphs[i].x;
|
||||
}
|
||||
if (glyphs[i].y < smallestY) {
|
||||
smallestY = (INT32)glyphs[i].y;
|
||||
}
|
||||
if (glyphs[i].y > largestY) {
|
||||
largestY = (INT32)glyphs[i].y;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Here we try to get a rough estimate of the area that this glyph run will
|
||||
* cover on the surface. Since we use GDI interop to draw we will be copying
|
||||
* data around the size of the area of the surface that we map. We will want
|
||||
* to map an area as small as possible to prevent large surfaces to be
|
||||
* copied around. We take the X/Y-size of the font as margin on the left/top
|
||||
* twice the X/Y-size of the font as margin on the right/bottom.
|
||||
* This should always cover the entire area where the glyphs are.
|
||||
*/
|
||||
RECT fontArea;
|
||||
fontArea.left = (INT32)(smallestX - scaled_font->font_matrix.xx);
|
||||
fontArea.right = (INT32)(largestX + scaled_font->font_matrix.xx * 2);
|
||||
fontArea.top = (INT32)(smallestY - scaled_font->font_matrix.yy);
|
||||
fontArea.bottom = (INT32)(largestY + scaled_font->font_matrix.yy * 2);
|
||||
if (fontArea.left < 0)
|
||||
fontArea.left = 0;
|
||||
if (fontArea.top < 0)
|
||||
fontArea.top = 0;
|
||||
if (fontArea.bottom > dst->extents.height) {
|
||||
fontArea.bottom = dst->extents.height;
|
||||
}
|
||||
if (fontArea.right > dst->extents.width) {
|
||||
fontArea.right = dst->extents.width;
|
||||
}
|
||||
if (fontArea.right <= fontArea.left ||
|
||||
fontArea.bottom <= fontArea.top) {
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
if (fontArea.right > dst->extents.width) {
|
||||
fontArea.right = dst->extents.width;
|
||||
}
|
||||
if (fontArea.bottom > dst->extents.height) {
|
||||
fontArea.bottom = dst->extents.height;
|
||||
}
|
||||
|
||||
run.bidiLevel = 0;
|
||||
run.fontFace = dwriteff->dwriteface;
|
||||
run.isSideways = FALSE;
|
||||
if (dwritesf->mat.xy == 0 && dwritesf->mat.yx == 0 &&
|
||||
dwritesf->mat.xx == scaled_font->font_matrix.xx &&
|
||||
dwritesf->mat.yy == scaled_font->font_matrix.yy) {
|
||||
|
||||
for (int i = 0; i < num_glyphs; i++) {
|
||||
indices[i] = (WORD) glyphs[i].index;
|
||||
// Since we will multiply by our ctm matrix later for rotation effects
|
||||
// and such, adjust positions by the inverse matrix now.
|
||||
offsets[i].ascenderOffset = (FLOAT)(fontArea.top - glyphs[i].y);
|
||||
offsets[i].advanceOffset = (FLOAT)(glyphs[i].x - fontArea.left);
|
||||
advances[i] = 0.0;
|
||||
}
|
||||
run.fontEmSize = (FLOAT)scaled_font->font_matrix.yy;
|
||||
} else {
|
||||
transform = TRUE;
|
||||
// See comment about EPSILON in _cairo_dwrite_glyph_run_from_glyphs
|
||||
const double EPSILON = 0.0001;
|
||||
for (int i = 0; i < num_glyphs; i++) {
|
||||
indices[i] = (WORD) glyphs[i].index;
|
||||
double x = glyphs[i].x - fontArea.left + EPSILON;
|
||||
double y = glyphs[i].y - fontArea.top;
|
||||
cairo_matrix_transform_point(&dwritesf->mat_inverse, &x, &y);
|
||||
/*
|
||||
* Since we will multiply by our ctm matrix later for rotation effects
|
||||
* and such, adjust positions by the inverse matrix now. The Y-axis
|
||||
* is inverted so the offset becomes negative.
|
||||
*/
|
||||
offsets[i].ascenderOffset = -(FLOAT)y;
|
||||
offsets[i].advanceOffset = (FLOAT)x;
|
||||
advances[i] = 0.0;
|
||||
}
|
||||
run.fontEmSize = 1.0f;
|
||||
}
|
||||
_cairo_dwrite_glyph_run_from_glyphs(glyphs, num_glyphs, dwritesf, &run, &transform);
|
||||
|
||||
cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)source;
|
||||
COLORREF color = RGB(((int)solid_pattern->color.red_short) >> 8,
|
||||
|
|
@ -1756,18 +1675,31 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface,
|
|||
mat = NULL;
|
||||
}
|
||||
|
||||
RECT area;
|
||||
area.left = dst->extents.x;
|
||||
area.top = dst->extents.y;
|
||||
area.right = area.left + dst->extents.width;
|
||||
area.bottom = area.top + dst->extents.height;
|
||||
RefPtr<IDWriteGlyphRunAnalysis> runAnalysis;
|
||||
HRESULT hr = DWriteFactory::Instance()->
|
||||
CreateGlyphRunAnalysis(&run, 1, mat,
|
||||
DWRITE_RENDERING_MODE_ALIASED,
|
||||
dwritesf->measuring_mode,
|
||||
0, // baselineOriginX,
|
||||
0, // baselineOriginY,
|
||||
&runAnalysis);
|
||||
if (FAILED(hr))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
RECT fontArea;
|
||||
hr = runAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_ALIASED_1x1, &fontArea);
|
||||
if (FAILED(hr))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
InflateRect(&fontArea, 1, 1);
|
||||
/* Needed to calculate bounding box for efficient blitting */
|
||||
RECT copyArea, dstArea = { 0, 0, dst->extents.width, dst->extents.height };
|
||||
IntersectRect(©Area, &fontArea, &dstArea);
|
||||
|
||||
#ifdef CAIRO_TRY_D2D_TO_GDI
|
||||
status = _dwrite_draw_glyphs_to_gdi_surface_d2d(dst,
|
||||
mat,
|
||||
&run,
|
||||
color,
|
||||
fontArea);
|
||||
copyArea);
|
||||
|
||||
if (status == (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
#endif
|
||||
|
|
@ -1776,7 +1708,7 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface,
|
|||
&run,
|
||||
color,
|
||||
dwritesf,
|
||||
fontArea);
|
||||
copyArea);
|
||||
|
||||
#ifdef CAIRO_TRY_D2D_TO_GDI
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue