Qt文本大小以磅为单位

时间:2018-04-27 17:43:23

标签: c++ qt text

我正在尝试以A4为单位打印发票凭证,而不是默认设备单位。除了将单位更改为毫米时,打印文档上的文本的分数不再与例如Word或Adobe Illustrator中的分数相匹配。我尝试将点大小转换为相应的像素大小,但它们存在问题。

QFont :: SetPixelSize只接受一个int,所以如果计算值低于1,它将会转换为0

font.setPixelSize((9.0 * 72.0) / printer.resolution());

另一种方法使文本的垂直尺寸正确,但有一些文物:

int phys_w = printer.width();
font.setPointSizeF((9.0 / phys_w) * 210.0);

enter image description here
你可以在哪里看到一些角色之间异常大的差距。 (也许Qt里面有一些精确的问题,它的文本绘图代码?)


以下是显示问题的最小示例:

QPrinter printer(QPrinter::HighResolution);
printer.setPageSize(QPrinter::A4);
printer.setOrientation(QPrinter::Portrait);
printer.setFullPage(true);
printer.setPageMargins(QMarginsF(0, 0, 0, 0));

printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOutputFileName("invoice.pdf");

QPainter painter(&printer);

auto page_size = printer.pageRect(QPrinter::Unit::Millimeter);
painter.setWindow(page_size.toRect());

QFont font = painter.font();

// Either this
font.setPixelSize((9.0 * 72.0) / printer.resolution());

// or this
int phys_w = printer.width();
font.setPointSizeF((9.0 / phys_w) * 210.0);

painter.setFont(font);
painter.drawText(35, 46, "John Doe");

如何以毫米(或任意单位)定位并使文字大小正确(或正确重新计算)?

这是在Qt 5.10.0和Windows 10上。

修改 最后,我选择了10倍的比例增加(十分之一毫米),这修复了setPointSizeF可见的字距调整问题。现在我对缩放的最后一个问题是设置一条线的宽度和其他形状(QPen :: setWidth),我找不到计算所以它以毫米为单位。

修改 最后,线宽不需要任何重新计算。最终代码如下:

QPrinter printer(QPrinter::HighResolution);
printer.setPageSize(QPrinter::A4);
printer.setOrientation(QPrinter::Portrait);
printer.setFullPage(true);
printer.setPageMargins(QMarginsF(0, 0, 0, 0));

printer.setOutputFormat(QPrinter::NativeFormat);

QPainter painter(&printer);
painter.setWindow(0, 0, 2100, 2970);
painter.setViewport(0, 0, printer.width(), printer.height());

QFont font(fontFamily, 0, weight, italic);
font.setPointSizeF(static_cast<float>(pixelSize) / printer.width() * 2100);

2 个答案:

答案 0 :(得分:2)

我认为你要划分你应该成倍增加的地方,反之亦然。看看明确写出的单位:

9分*(1英寸/ 72分)*(printer.res像素/英寸)

乘以单位,分子得到(点*英寸*像素),分母得到(点*英寸)。取消相似的单位,你会得到分子中的像素。所以计算应该是:

font.setPixelSize(9.0 / 72.0 * printer.resolution());

对于你的第二个问题,

QPen::setWidthF(w*printer.resolution()/25.4);

其中w是您所需的宽度,单位为mm。

答案 1 :(得分:1)

通过详细观察(打印一个长句),人们注意到角色之间的这些差距与角色本身直接相关,宽字符和大写字母占用了差距(J,s,r,c),而狭窄的角色则留下更多gap(i,l,t)..这只是说它不是随机行为。

一般来说,这被称为字距很好地解释here。为了最大限度地减少这种情况,Qt将QFont字距设置为true(默认值)QFont Kerning ...但问题是字距调整在很大程度上取决于使用的字体和像素,启用Qt字距调整有时不会像{{3可能是因为将 Kerning 设置为true

  

(将在相邻字形之间应用字距调整。请注意OpenType GPOS   目前不支持基于字距调整 this post

这意味着某些字体 Ascent / Descent 仍将限制如何控制间隙。 下面考虑两个解决方案,第一个仍然坚持使用默认的painter字体,但你可以拉伸字符来强制执行合理的gab:

font.setStretch(70); // value is experimental 

QRawFont::LayoutFlags

我不认为这是一个强大的解决方案,除非限制使用特定字体,而字体本身对于发票打印并不重要,第二个有吸引力的方法是找出最符合的字体要求:在绘制PDF(从Qt)时,设置分辨率/损失很小,并且对于字距调整最有效! 例如,“ MS Gothic ”(ttf)在这种设置中表现良好,这里表现如何(不拉伸)

painter.setFont(QFont("MS Gothic"));
QFont font = painter.font();
int phys_w = printer.width();
font.setPointSizeF((9.0 / phys_w) * 210.0);
//font.setStretch(70);
painter.setFont(font);

enter image description here

选择合适字体的好处是可以进行更多控制(特别是对于小空间有价值的发票打印)。

例如,通过减少字母之间的差距可以打印更少的空间:

font.setLetterSpacing(QFont::PercentageSpacing,65); // 65% gap of default

enter image description here

人们可以在不失去视觉清除的情况下获得较低的字体大小。

分享下面的一些工作,同时试图澄清打印小字体是如何影响字母之间的差距。我们的想法是在QRect内单独绘制每个角色,同时在同一区域绘制等效的QRectF。

当看到字体大小很大时,QRectF被绘制成彼此相邻,所以每个字符也是......当字体大小变小时,相邻的QRectF将严重重叠,字符之间的间隙开始变得混乱。

QPen pen=painter.pen();
pen.setWidth(0.1);
painter.setPen(pen);
QString td("John Doe");
auto spacer = font.pointSizeF(); // font size used to set width of QRect of each character.
spacer *=30.0; // large Rect width.
auto b = 35.0;

for (int i=0; i < td.length() ;i++ )
{
    QRectF rectf(b+=spacer,47.0,4.0,4.0);
    QRect rect(b, 47.0,4.0,4.0);
    QString ch = td.at(i);
    //painter.drawText(b+=spacer,46,ch);
    painter.drawText(rect,Qt::AlignCenter,ch);
    painter.drawRect(rectf);
}
painter.end();

大字体的结果:

enter image description here

接下来使QRectF重叠:

spacer *=10.0;

结果,字母间隙越来越小,相邻字符越宽,间隙越小。

enter image description here