我正在尝试以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);
你可以在哪里看到一些角色之间异常大的差距。 (也许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);
答案 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
我不认为这是一个强大的解决方案,除非限制使用特定字体,而字体本身对于发票打印并不重要,第二个有吸引力的方法是找出最符合的字体要求:在绘制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);
选择合适字体的好处是可以进行更多控制(特别是对于小空间有价值的发票打印)。
例如,通过减少字母之间的差距可以打印更少的空间:
font.setLetterSpacing(QFont::PercentageSpacing,65); // 65% gap of default
人们可以在不失去视觉清除的情况下获得较低的字体大小。
分享下面的一些工作,同时试图澄清打印小字体是如何影响字母之间的差距。我们的想法是在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();
大字体的结果:
接下来使QRectF重叠:
spacer *=10.0;
结果,字母间隙越来越小,相邻字符越宽,间隙越小。