Skip to content
This repository was archived by the owner on Mar 7, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fixes
Don't adjust baseline on vertical text. It needs to be handled
differently to horizontal, and has enough other problems that I don't
want to start. Fixes test failure.

Fixes the compile error that happened for Windows.

Report the baseline offset separately to the box offset, because it
needs to be handled differently for measurement etc. Basically when
drawing it needs to make it draw lower (affecting position), but when
measuring it needs to make the rectangle taller (affecting size but
leaving the position unchanged).
  • Loading branch information
PreferLinux committed Sep 3, 2020
commit 428fda636b350b6fc02a72b43a3fc9631b6ee917
5 changes: 3 additions & 2 deletions src/graphics-path.c
Original file line number Diff line number Diff line change
Expand Up @@ -1273,6 +1273,7 @@ GdipAddPathString (GpPath *path, GDIPCONST WCHAR *string, int length,
{
GpRectF box;
GpPointF box_offset;
float baseline_offset;
PangoLayout* layout;
GpStringFormat *string_format;

Expand All @@ -1296,8 +1297,8 @@ GdipAddPathString (GpPath *path, GDIPCONST WCHAR *string, int length,
return status;
}

layout = gdip_pango_setup_layout (cr, string, length, font, layoutRect, &box, &box_offset, string_format, NULL);
cairo_move_to (cr, layoutRect->X + box_offset.X, layoutRect->Y + box_offset.Y);
layout = gdip_pango_setup_layout (cr, string, length, font, layoutRect, &box, &box_offset, &baseline_offset, string_format, NULL);
cairo_move_to (cr, layoutRect->X + box_offset.X, layoutRect->Y + box_offset.Y + baseline_offset);
pango_cairo_layout_path (cr, layout);
g_object_unref (layout);

Expand Down
2 changes: 1 addition & 1 deletion src/text-pango-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@


PangoLayout* gdip_pango_setup_layout (cairo_t *cr, GDIPCONST WCHAR *stringUnicode, INT length, GDIPCONST GpFont *font,
GDIPCONST RectF *rc, RectF *box, PointF *box_offset, GDIPCONST GpStringFormat *format, INT **charsRemoved);
GDIPCONST RectF *rc, RectF *box, PointF *box_offset, float *baseline_offset, GDIPCONST GpStringFormat *format, INT **charsRemoved);

GpStatus pango_DrawString (GpGraphics *graphics, GDIPCONST WCHAR *stringUnicode, INT length, GDIPCONST GpFont *font,
GDIPCONST RectF *rc, GDIPCONST GpStringFormat *format, GpBrush *brush) GDIP_INTERNAL;
Expand Down
45 changes: 26 additions & 19 deletions src/text-pango.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ gdip_process_string (gchar *text, int length, int removeAccelerators, int trimSp

PangoLayout*
gdip_pango_setup_layout (cairo_t *cr, GDIPCONST WCHAR *stringUnicode, int length, GDIPCONST GpFont *font,
GDIPCONST RectF *rc, RectF *box, PointF *box_offset, GDIPCONST GpStringFormat *format, int **charsRemoved)
GDIPCONST RectF *rc, RectF *box, PointF *box_offset, float *baseline_offset, GDIPCONST GpStringFormat *format, int **charsRemoved)
{
GpStringFormat *fmt;
PangoLayout *layout;
Expand Down Expand Up @@ -468,24 +468,26 @@ gdip_pango_setup_layout (cairo_t *cr, GDIPCONST WCHAR *stringUnicode, int length

box_offset->X = 0;
box_offset->Y = 0;
*baseline_offset = 0;

switch (fmt->lineAlignment) {
case StringAlignmentNear: {
// Some fonts have interesting metrics, and cause Pango to position them differently to Windows.
// For instance, Calibri and the free metric-equivalent Carlito. It is positioned higher, because Pango
// uses a different ascent value than Windows. We can handle that by drawing it slightly lower.
uint16_t ascent;
uint16_t em_size;
if (GdipGetCellAscent(font->family, (INT) font->style, &ascent) == Ok &&
GdipGetEmHeight(font->family, (INT) font->style, &em_size) == Ok) {

int baseline = pango_layout_get_baseline(layout) / PANGO_SCALE;
int correct_baseline = (int) ceil(font->sizeInPixels / em_size * ascent);
if (baseline < correct_baseline)
box_offset->Y = correct_baseline - baseline;
case StringAlignmentNear:
if (!(fmt->formatFlags & StringFormatFlagsDirectionVertical)) {
// Some fonts have interesting metrics, and cause Pango to position them differently to Windows.
// For instance, Calibri and the free metric-equivalent Carlito. It is positioned higher, because Pango
// uses a different ascent value than Windows. We can handle that by drawing it slightly lower.
USHORT ascent;
USHORT em_size;
if (GdipGetCellAscent(font->family, (INT) font->style, &ascent) == Ok &&
GdipGetEmHeight(font->family, (INT) font->style, &em_size) == Ok) {

int baseline = pango_layout_get_baseline(layout) / PANGO_SCALE;
int correct_baseline = (int) ceil(font->sizeInPixels / em_size * ascent);
if (baseline < correct_baseline)
*baseline_offset = correct_baseline - baseline;
}
}
break;
}
case StringAlignmentCenter:
box_offset->Y += (FrameHeight - box->Height) * 0.5;
break;
Expand Down Expand Up @@ -542,6 +544,7 @@ pango_DrawString (GpGraphics *graphics, GDIPCONST WCHAR *stringUnicode, INT leng
PangoLayout *layout;
RectF box;
PointF box_offset;
float baseline_offset;

/* Setup cairo */
if (brush) {
Expand All @@ -552,7 +555,7 @@ pango_DrawString (GpGraphics *graphics, GDIPCONST WCHAR *stringUnicode, INT leng

cairo_save (graphics->ct);

layout = gdip_pango_setup_layout (graphics->ct, stringUnicode, length, font, rc, &box, &box_offset, format, NULL);
layout = gdip_pango_setup_layout (graphics->ct, stringUnicode, length, font, rc, &box, &box_offset, &baseline_offset, format, NULL);
if (!layout) {
cairo_restore (graphics->ct);
return OutOfMemory;
Expand All @@ -566,7 +569,7 @@ pango_DrawString (GpGraphics *graphics, GDIPCONST WCHAR *stringUnicode, INT leng
cairo_clip (graphics->ct);
}

gdip_cairo_move_to (graphics, rc->X + box_offset.X, rc->Y + box_offset.Y, FALSE, TRUE);
gdip_cairo_move_to (graphics, rc->X + box_offset.X, rc->Y + box_offset.Y + baseline_offset, FALSE, TRUE);
pango_cairo_show_layout (graphics->ct, layout);

g_object_unref (layout);
Expand All @@ -583,15 +586,17 @@ pango_MeasureString (GpGraphics *graphics, GDIPCONST WCHAR *stringUnicode, INT l
PangoRectangle logical;
PangoLayoutIter *iter;
PointF box_offset;
float baseline_offset;
int *charsRemoved = NULL;

cairo_save (graphics->ct);

layout = gdip_pango_setup_layout (graphics->ct, stringUnicode, length, font, rc, boundingBox, &box_offset, format, &charsRemoved);
layout = gdip_pango_setup_layout (graphics->ct, stringUnicode, length, font, rc, boundingBox, &box_offset, &baseline_offset, format, &charsRemoved);
if (!layout) {
cairo_restore (graphics->ct);
return OutOfMemory;
}
boundingBox->Height += baseline_offset;

if (codepointsFitted || linesFilled) {
int charsFitted;
Expand Down Expand Up @@ -692,6 +697,7 @@ pango_MeasureCharacterRanges (GpGraphics *graphics, GDIPCONST WCHAR *stringUnico
int i, j;
GpRectF boundingBox;
GpPointF box_offset;
float baseline_offset;

if (layoutRect->Width <= 0.0 && layoutRect->Height < 0.0) {
/* special case only if BOTH values are negative */
Expand All @@ -702,7 +708,7 @@ pango_MeasureCharacterRanges (GpGraphics *graphics, GDIPCONST WCHAR *stringUnico

cairo_save (graphics->ct);

layout = gdip_pango_setup_layout (graphics->ct, stringUnicode, length, font, layoutRect, &boundingBox, &box_offset, format, NULL);
layout = gdip_pango_setup_layout (graphics->ct, stringUnicode, length, font, layoutRect, &boundingBox, &box_offset, &baseline_offset, format, NULL);
if (!layout) {
cairo_restore (graphics->ct);
return OutOfMemory;
Expand Down Expand Up @@ -764,6 +770,7 @@ pango_MeasureCharacterRanges (GpGraphics *graphics, GDIPCONST WCHAR *stringUnico
}
charRect.X += box_offset.X + layoutRect->X;
charRect.Y += box_offset.Y + layoutRect->Y;
charRect.Height += baseline_offset;
// g_warning ("[%d] [%d : %d-%d] %c [x %g y %g w %g h %g]", i, j, start, end, (char)stringUnicode[j], charRect.X, charRect.Y, charRect.Width, charRect.Height);
status = GdipCombineRegionRect (regions [i], &charRect, CombineModeUnion);
if (status != Ok)
Expand Down