月度归档:2022年11月

在cairo中使用pango文字渲染的文本显示区域是如何计算的

首先,pango可以使用pango_layout_get_pixel_extents获取ink_rect和logical_rect。

// API声明
void pango_layout_get_extents (PangoLayout    *layout,
			  PangoRectangle *ink_rect,
			  PangoRectangle *logical_rect);
// 调用示例
PangoRectangle rcInk, rcLogic;
pango_layout_get_pixel_extents(layout, &rcInk, &rcLogic);

假设使用cairo在(0, 0)位置输出文本”选项1″三个字,使用以上代码获取的 rcInk值为(x=0, y=6, w=52, h=19),rcLogi的值为(0,0,51,30)。那么输出的文字几个关键位置如下:

在绘制时,rcInk.y的值是实际墨迹的y方向起始值,可以理解为文字的顶部空白部分。这个空白在英文字母的绘制中比较明显,比如a会比i的rcInk.y的值更大,因为在四线三格中

垂直居中对齐:上图的是一个文本框的示意图,如果让“墨迹区域”在文本框box内垂直居中显示,可以按如下代码计算oy的值。

rcInk, rcLogic; 
...

topspace = rcInk.y;
oy = (box.h - ink.h) / 2 - topspace;

...
cairo_move(x, oy);
....

底部对齐:底部对齐可按如下方法 计算oy的值

rcInk, rcLogic; 
...

topspace = rcInk.y;
oy = box.h - ink.h - topsace;

...
cairo_move(x, oy);
....

关于windows系统的SetCapture

当我们需要精细化处理某个窗口的WM_MOUSEMOVE事件时,需要使用到SetCapture()。它使我们的程序可以在鼠标移出窗口区域、或在DISABLE的窗口中响应MouseMove事件。

正常情况下,我们会在WM_SETCURSOR事件中设置捕获。然后在鼠标移出窗口区域时释放捕获:

case WM_SETCURSOR:
    SetCapture(hWnd);
    break;

case WM_MOUSEMOVE:
    if (x < 0 || x > width)
        ReleaseCapture();

在Windows系统中,被 SetCapture的窗口在同一时刻只能有一个。并且当一个窗口SetCapture时,其它窗口无论是否处于上层,都将无法响应鼠标事件。所以当两个都需要设置Cature的窗口有重叠区域时,需要额外处理鼠标捕获。

如下图,窗口B在A的上层。当鼠标从起始点进入窗口A时,窗口A会首先SetCapture。但当鼠标向右移动到窗口B时,因为窗口A的Capture,窗口B是无法响应鼠标事件的。如果窗口A已经按上文描述在鼠标移出窗口A时释放捕获。当鼠标继续向右移出窗口A时,窗口B可开始捕获。

在实际应用中,可在MouseMove事件中即时检查鼠标坐标处的顶层窗口。如上图的情形,当鼠标“进入B”时,可在窗口A中释放捕获,交由窗口B继续处理。