【问题标题】:Why is this stroke so fragmented and why does it only stroke the inside?为什么这个中风如此支离破碎,为什么只中风内部?
【发布时间】:2015-05-29 22:06:10
【问题描述】:

我正在使用 LineBreakMeasurer 和 TextLayout 在图像上绘制一些文本,但由于某种原因,笔触只是在内部抚摸,而且不是很干净。 这是我正在谈论的一个例子: http://i.imgur.com/eHtTw4p.png

当我不把字母画在上面并增加笔画宽度时,它实际上会在里面变粗而不是在外面。

这是我的代码:

        float y = 0.0f;
        float wrappingWidth = img.getWidth() * 0.8f;
        LineBreakMeasurer measurer = new LineBreakMeasurer(str.getIterator(), imageGraphics.getFontRenderContext());
        while (measurer.getPosition() < sentence.length()) {
            TextLayout layout = measurer.nextLayout(wrappingWidth);
            y += layout.getAscent();
            float x =  ((wrappingWidth * 0.8f) - layout.getVisibleAdvance()) / 2f + (wrappingWidth * 0.2f);

            AffineTransform transform = new AffineTransform();
            transform.translate((double)x, (double)y);
            Shape outline = layout.getOutline(transform);

            imageGraphics.setColor(Color.black);
            imageGraphics.setClip(outline);
            imageGraphics.setStroke(new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER));
            imageGraphics.draw(outline);
            imageGraphics.setColor(Color.white);
            imageGraphics.setStroke(new BasicStroke());

            layout.draw(imageGraphics, x, y);
            y += layout.getDescent() + layout.getLeading();
        }

我不确定我做错了什么。有人知道吗?

【问题讨论】:

  • 你考虑过翻译outline吗? outline 将被绘制在与文本相同的位置?此外,您永远不会重置笔画,因此文本很可能是用相同的笔画绘制的......
  • 关于未重置笔划位的信息很好。我最初正在重置它,但想看看如果我使用相同的笔划,两者是否会完美重叠。显然不是。但是,是的,当我重置笔画时,结果完全相同。我没有意识到有必要翻译大纲?笔画不应该从两边加宽吗?
  • 我对@9​​87654326@ 不太熟悉,但这对我来说似乎有点不寻常:imageGraphics.setClip(outline); 剪辑可能会遮挡笔触(填充在形状之外)。这也可能是RenderingHints 问题。
  • 我认为它会在笔画之前将其剪辑,因此不会遮挡它?我删除了剪裁,笔画现在实际上正在工作。只是质量真的很差。 i.imgur.com/ztSW7FS.png

标签: java awt java-2d


【解决方案1】:

在绘制轮廓之前创建Graphics 上下文的另一个副本...

Graphics2D sg = (Graphics2D)imageGraphics.create();
sg.setColor(Color.black);
sg.setStroke(new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER));
sg.draw(outline);
sg.dispose();

我也会摆脱剪辑...

例如,我不想“抚摸”生成的形状,而是试图“填充”背景颜色并在其上“绘制”轮廓颜色......

Graphics2D sg = (Graphics2D) g2d.create();
AffineTransform transform = new AffineTransform();
transform.translate((double) drawPosX, (double) drawPosY);
Shape outline = layout.getOutline(transform);

sg.setColor(Color.WHITE);
sg.fill(outline);
sg.setColor(Color.BLACK);
sg.draw(outline);
sg.dispose();

但如果你想要“漂亮”的粗笔画,请使用BasicStroke.JOIN_ROUND 而不是BasicStroke.JOIN_MITER

Graphics2D sg = (Graphics2D) g2d.create();
AffineTransform transform = new AffineTransform();
transform.translate((double) drawPosX, (double) drawPosY);
Shape outline = layout.getOutline(transform);

sg.setStroke(new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
sg.setColor(Color.BLACK);
sg.draw(outline);
sg.dispose();

【讨论】:

  • 效果很好。回想起来,我不知道我为什么要尝试抚摸角色的外部。我猜,来自图形编辑器的一些意识形态模糊了我的判断:)非常感谢。
  • “使用 JOIN_ROUND 代替 JOIN_ROUND”?
  • @immibis 复制粘贴可不妙。创建第二个Graphics 上下文的目的是为了保护原始上下文免受我可能做出的任何更改(例如应用新的笔划或转换),调用Graphics#dispose 然后计算出如何退出一个化合物要简单得多您可能会忘记的转换或其他更改
  • 来自这个answer的相同的;)
  • 顺便说一句,在某些情况下,一些字体(即影响)的渲染提示存在一些小问题。我将插值更改为双三次,现在已解决:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-06
  • 1970-01-01
  • 1970-01-01
  • 2013-11-16
  • 1970-01-01
  • 2018-05-20
相关资源
最近更新 更多