形状内文本环绕算法

发布于 2024-09-05 18:41:17 字数 164 浏览 6 评论 0原文

我正在寻找一种将文本包装在非矩形形状内的算法,最好基于 Knuth 和 Plass 算法。最困难的部分是,由于文本中不同的字体大小,线条可能具有不同的高度。下图是算法应该能够生成的示例。

心形文字

I am looking for an algorithm to wrap text within a non-rectangular shape, preferably based on the Knuth and Plass algorithm. The hardest part of this is that the lines may have different heights due to differing font sizes in the text. The image below is an example of what the algorithm should be able to generate.

Text shaped like a heart

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

﹉夏雨初晴づ 2024-09-12 18:41:19

编辑,更新

尝试

text / html

    
        gggggggggggggg              gggggggggggggg 
     gggggggggggggggggggg         gggggggggggggggggg
   gggggggggggggggggggggggg     gggggggggggggggggggggg
 ggggggggggggggggggggggggggg   ggggggggggggggggggggggggg
ggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
 gggggggggggggggggggggggggggggggggggggggggggggggggggggggg
  gggggggggggggggggggggggggggggggggggggggggggggggggggggg
   gggggggggggggggggggggggggggggggggggggggggggggggggggg
     ggggggggggggggggggggggggggggggggggggggggggggggggg
      gggggggggggggggggggggggggggggggggggggggggggggg
        gggggggggggggggggggggggggggggggggggggggggg
           ggggggggggggggggggggggggggggggggggggg
              gggggggggggggggggggggggggggggg
                 gggggggggggggggggggggggg
                    gggggggggggggggggg
                       gggggggggggg
                         gggggggg
                           ggggg
                            ggg
                             g

js

var text =  "Lorem ipsum dolor sit amet," // `string` , `array` 
, i = -1
, elem = document.querySelector("pre");
elem.innerText = elem.innerText.replace(/[^\n|\r|\t|\s+]/g, function() {
                   return text[++i] 
                 });

        Lorem ipsum do              lor sit amet,  
     consectetur adipisci         ng elit. Vivamus b
   landit nisl eu posuere s     uscipit. Etiam at quam
  sed nulla consequat finibu   s et eget ligula. Nam sit
 amet imperdiet eros. Ut a congue nibh. Sed ac arcu non r
isus commodo lobortis et at lorem. Pellentesque pulvinar v
enenatis pellentesque. Praesent sed pulvinar justo. Ut nec
 turpis lectus. Suspendisse porta ipsum orci, nec vestibul
um tellus luctus quis. Morbi eleifend vel nibh sed rutrum.
 Etiam feugiat, nunc et efficitur accumsan, quam magna lac
 inia neque, eu ullamcorper purus turpis eget urna. Etiam
   lacus mi, gravida vel mollis ut, viverra sed ipsum. M
   auris in augue turpis.Nulla facilisi. In tristique t
     ortor sit amet leo cursus, sit amet varius ligula
       sollicitudin. Mauris commodo et sapien id sce
        lerisque. Integer et diam eget arcu bibend
           um ornare a in tortor. Lorem ipsum do
              lor sit amet, consectetur adip
                 iscing elit. Aliquam veh
                    icula diam ac laor
                       eet tincidun
                         t. Integ
                           er se
                            d t
                             e

var text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus blandit nisl eu posuere suscipit. Etiam at quam sed nulla consequat finibus et eget ligula. Nam sit amet imperdiet eros. Ut a congue nibh. Sed ac arcu non risus commodo lobortis et at lorem. Pellentesque pulvinar venenatis pellentesque. Praesent sed pulvinar justo. Ut nec turpis lectus. Suspendisse porta ipsum orci, nec vestibulum tellus luctus quis. Morbi eleifend vel nibh sed rutrum. Etiam feugiat, nunc et efficitur accumsan, quam magna lacinia neque, eu ullamcorper purus turpis eget urna. Etiam lacus mi, gravida vel mollis ut, viverra sed ipsum. Mauris in augue turpis."

+ "Nulla facilisi. In tristique tortor sit amet leo cursus, sit amet varius ligula sollicitudin. Mauris commodo et sapien id scelerisque. Integer et diam eget arcu bibendum ornare a in tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vehicula diam ac laoreet tincidunt. Integer sed tellus sit amet lacus bibendum tristique a a nulla. Quisque venenatis suscipit est eget ultricies. Quisque ac orci convallis, interdum enim quis, dictum justo. Phasellus tincidunt nisi vitae justo fringilla, sit amet pellentesque enim dictum. Duis porttitor convallis feugiat. Sed lectus massa, consectetur et vestibulum a, egestas ac eros. Proin mollis ligula tellus, a dignissim eros placerat sed. Donec vel blandit magna. Etiam quis tortor rhoncus, porta ante et, pretium mi."

+ "Vestibulum ut risus convallis, sagittis orci sed, faucibus erat. Aliquam maximus suscipit lectus, vel pellentesque enim dictum nec. Sed et ex id mauris finibus molestie. Aliquam erat volutpat. Etiam nec ultricies est. Aenean vitae mi id neque vulputate suscipit vel vitae ante. Nam sit amet mi diam. Phasellus efficitur faucibus viverra. Proin cursus purus et tortor dictum elementum. Nunc vehicula erat volutpat, rutrum metus bibendum, blandit sem."

+ "Nam eu ante eros. Sed pellentesque accumsan neque, eu vulputate lectus luctus ac. In hac habitasse platea dictumst. Nulla vitae dictum diam. Sed eget mauris in felis luctus luctus. Mauris volutpat lacus in est dignissim, sit amet venenatis ipsum laoreet. Phasellus semper id velit ut tristique. Proin dictum erat at mauris lacinia blandit. Ut scelerisque mi ex, ut pretium elit commodo sit amet. Praesent faucibus turpis tellus, ac vulputate felis aliquet eget. Ut est urna, dignissim nec risus sit amet, eleifend lacinia enim. Donec non massa in purus efficitur placerat. Donec accumsan neque elit, eget vulputate metus finibus quis. Ut interdum sem vel felis imperdiet pretium. Integer erat neque, bibendum id egestas nec, facilisis sed massa."

+ "Curabitur sit amet mattis odio. Mauris mattis turpis eu lectus eleifend, semper ultrices elit malesuada. Mauris fringilla arcu sed sem vehicula vulputate. Donec semper nisl ut urna bibendum, quis eleifend tortor commodo. Pellentesque vehicula est et neque vulputate accumsan. Duis faucibus sodales lacus et suscipit. Pellentesque tortor enim, pulvinar scelerisque pretium non, aliquam sed risus. Vestibulum aliquam dolor ipsum, eget pretium ante fermentum a. Donec semper lectus pulvinar tellus hendrerit sagittis. Nunc blandit sed ligula vel consequat. Etiam sed est quis nulla blandit blandit. Sed in enim pulvinar elit accumsan faucibus sed sodales lorem. Aenean ac efficitur arcu, sed fringilla lectus."

, i = -1;
var elem = document.querySelector("pre");
elem.innerText = elem.innerText.replace(/[^\n|\r|\t|\s+]/g, function() {
                   return text[++i] 
                 });
<pre>    
        gggggggggggggg              gggggggggggggg 
     gggggggggggggggggggg         gggggggggggggggggg
   gggggggggggggggggggggggg     gggggggggggggggggggggg
 ggggggggggggggggggggggggggg   ggggggggggggggggggggggggg
ggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
 gggggggggggggggggggggggggggggggggggggggggggggggggggggggg
  gggggggggggggggggggggggggggggggggggggggggggggggggggggg
   gggggggggggggggggggggggggggggggggggggggggggggggggggg
     ggggggggggggggggggggggggggggggggggggggggggggggggg
      gggggggggggggggggggggggggggggggggggggggggggggg
        gggggggggggggggggggggggggggggggggggggggggg
           ggggggggggggggggggggggggggggggggggggg
              gggggggggggggggggggggggggggggg
                 gggggggggggggggggggggggg
                    gggggggggggggggggg
                       gggggggggggg
                         gggggggg
                           ggggg
                            ggg
                             g
</pre>

Edit, Updated

Try

text / html

    
        gggggggggggggg              gggggggggggggg 
     gggggggggggggggggggg         gggggggggggggggggg
   gggggggggggggggggggggggg     gggggggggggggggggggggg
 ggggggggggggggggggggggggggg   ggggggggggggggggggggggggg
ggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
 gggggggggggggggggggggggggggggggggggggggggggggggggggggggg
  gggggggggggggggggggggggggggggggggggggggggggggggggggggg
   gggggggggggggggggggggggggggggggggggggggggggggggggggg
     ggggggggggggggggggggggggggggggggggggggggggggggggg
      gggggggggggggggggggggggggggggggggggggggggggggg
        gggggggggggggggggggggggggggggggggggggggggg
           ggggggggggggggggggggggggggggggggggggg
              gggggggggggggggggggggggggggggg
                 gggggggggggggggggggggggg
                    gggggggggggggggggg
                       gggggggggggg
                         gggggggg
                           ggggg
                            ggg
                             g

js

var text =  "Lorem ipsum dolor sit amet," // `string` , `array` 
, i = -1
, elem = document.querySelector("pre");
elem.innerText = elem.innerText.replace(/[^\n|\r|\t|\s+]/g, function() {
                   return text[++i] 
                 });

        Lorem ipsum do              lor sit amet,  
     consectetur adipisci         ng elit. Vivamus b
   landit nisl eu posuere s     uscipit. Etiam at quam
  sed nulla consequat finibu   s et eget ligula. Nam sit
 amet imperdiet eros. Ut a congue nibh. Sed ac arcu non r
isus commodo lobortis et at lorem. Pellentesque pulvinar v
enenatis pellentesque. Praesent sed pulvinar justo. Ut nec
 turpis lectus. Suspendisse porta ipsum orci, nec vestibul
um tellus luctus quis. Morbi eleifend vel nibh sed rutrum.
 Etiam feugiat, nunc et efficitur accumsan, quam magna lac
 inia neque, eu ullamcorper purus turpis eget urna. Etiam
   lacus mi, gravida vel mollis ut, viverra sed ipsum. M
   auris in augue turpis.Nulla facilisi. In tristique t
     ortor sit amet leo cursus, sit amet varius ligula
       sollicitudin. Mauris commodo et sapien id sce
        lerisque. Integer et diam eget arcu bibend
           um ornare a in tortor. Lorem ipsum do
              lor sit amet, consectetur adip
                 iscing elit. Aliquam veh
                    icula diam ac laor
                       eet tincidun
                         t. Integ
                           er se
                            d t
                             e

var text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus blandit nisl eu posuere suscipit. Etiam at quam sed nulla consequat finibus et eget ligula. Nam sit amet imperdiet eros. Ut a congue nibh. Sed ac arcu non risus commodo lobortis et at lorem. Pellentesque pulvinar venenatis pellentesque. Praesent sed pulvinar justo. Ut nec turpis lectus. Suspendisse porta ipsum orci, nec vestibulum tellus luctus quis. Morbi eleifend vel nibh sed rutrum. Etiam feugiat, nunc et efficitur accumsan, quam magna lacinia neque, eu ullamcorper purus turpis eget urna. Etiam lacus mi, gravida vel mollis ut, viverra sed ipsum. Mauris in augue turpis."

+ "Nulla facilisi. In tristique tortor sit amet leo cursus, sit amet varius ligula sollicitudin. Mauris commodo et sapien id scelerisque. Integer et diam eget arcu bibendum ornare a in tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vehicula diam ac laoreet tincidunt. Integer sed tellus sit amet lacus bibendum tristique a a nulla. Quisque venenatis suscipit est eget ultricies. Quisque ac orci convallis, interdum enim quis, dictum justo. Phasellus tincidunt nisi vitae justo fringilla, sit amet pellentesque enim dictum. Duis porttitor convallis feugiat. Sed lectus massa, consectetur et vestibulum a, egestas ac eros. Proin mollis ligula tellus, a dignissim eros placerat sed. Donec vel blandit magna. Etiam quis tortor rhoncus, porta ante et, pretium mi."

+ "Vestibulum ut risus convallis, sagittis orci sed, faucibus erat. Aliquam maximus suscipit lectus, vel pellentesque enim dictum nec. Sed et ex id mauris finibus molestie. Aliquam erat volutpat. Etiam nec ultricies est. Aenean vitae mi id neque vulputate suscipit vel vitae ante. Nam sit amet mi diam. Phasellus efficitur faucibus viverra. Proin cursus purus et tortor dictum elementum. Nunc vehicula erat volutpat, rutrum metus bibendum, blandit sem."

+ "Nam eu ante eros. Sed pellentesque accumsan neque, eu vulputate lectus luctus ac. In hac habitasse platea dictumst. Nulla vitae dictum diam. Sed eget mauris in felis luctus luctus. Mauris volutpat lacus in est dignissim, sit amet venenatis ipsum laoreet. Phasellus semper id velit ut tristique. Proin dictum erat at mauris lacinia blandit. Ut scelerisque mi ex, ut pretium elit commodo sit amet. Praesent faucibus turpis tellus, ac vulputate felis aliquet eget. Ut est urna, dignissim nec risus sit amet, eleifend lacinia enim. Donec non massa in purus efficitur placerat. Donec accumsan neque elit, eget vulputate metus finibus quis. Ut interdum sem vel felis imperdiet pretium. Integer erat neque, bibendum id egestas nec, facilisis sed massa."

+ "Curabitur sit amet mattis odio. Mauris mattis turpis eu lectus eleifend, semper ultrices elit malesuada. Mauris fringilla arcu sed sem vehicula vulputate. Donec semper nisl ut urna bibendum, quis eleifend tortor commodo. Pellentesque vehicula est et neque vulputate accumsan. Duis faucibus sodales lacus et suscipit. Pellentesque tortor enim, pulvinar scelerisque pretium non, aliquam sed risus. Vestibulum aliquam dolor ipsum, eget pretium ante fermentum a. Donec semper lectus pulvinar tellus hendrerit sagittis. Nunc blandit sed ligula vel consequat. Etiam sed est quis nulla blandit blandit. Sed in enim pulvinar elit accumsan faucibus sed sodales lorem. Aenean ac efficitur arcu, sed fringilla lectus."

, i = -1;
var elem = document.querySelector("pre");
elem.innerText = elem.innerText.replace(/[^\n|\r|\t|\s+]/g, function() {
                   return text[++i] 
                 });
<pre>    
        gggggggggggggg              gggggggggggggg 
     gggggggggggggggggggg         gggggggggggggggggg
   gggggggggggggggggggggggg     gggggggggggggggggggggg
 ggggggggggggggggggggggggggg   ggggggggggggggggggggggggg
ggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
 gggggggggggggggggggggggggggggggggggggggggggggggggggggggg
  gggggggggggggggggggggggggggggggggggggggggggggggggggggg
   gggggggggggggggggggggggggggggggggggggggggggggggggggg
     ggggggggggggggggggggggggggggggggggggggggggggggggg
      gggggggggggggggggggggggggggggggggggggggggggggg
        gggggggggggggggggggggggggggggggggggggggggg
           ggggggggggggggggggggggggggggggggggggg
              gggggggggggggggggggggggggggggg
                 gggggggggggggggggggggggg
                    gggggggggggggggggg
                       gggggggggggg
                         gggggggg
                           ggggg
                            ggg
                             g
</pre>

音盲 2024-09-12 18:41:19

假设每个字母都有特定的大小(宽度和高度,在这种情况下我们可能只关心宽度,因为所有字母都具有相同的高度)。然后我们需要以下内容:

  1. 下单词不会出现碎片
  2. 每个单词的包装对象 - 以确保在给定每个单词宽度的情况
  3. 。将多边形划分为单词高度的块。所以你有x条水平条组成了图像。
  4. 然后,如果要在内部刻字,请找到内部多边形的宽度。这意味着您要去除心脏的圆形边缘。垂直线可以与条带上的心形边缘相交的地方就是您删除圆形边缘的地方。

现在我们有了图像每个条带的大小,假设我们有这个(我使用任意单位作为宽度):

[_________] [__________]  <-- 10 width (5 each)
  [__________________] <-- 9 width
    [_____________] <-- 7 width   
       [_______] <-- 5 width
         [___] <-- 3 width
          [_] <-- 2 width

编辑:刚刚意识到心脏是多么丑陋,我的错。

现在我们需要每个单词的大小,并按顺序插入它们。每个块有 x 宽度,每个单词对象有 y 宽度。如果y宽度> x 宽度,我们移动到下一行并检查那里

considering we already have widths
while(image.hasNextChunk()){
    currentChunk = image.nextChunk();
    if(currentWord.width < currentChunk.width) //insert here and then change currentWord to nextWord
    ...
}

我认为这就是你想要的,但我不完全确定。让我知道这是否有帮助! :)

Let's say each letter has a specific size(width and height, in this case we probably only care about width because all letters have the same height). Then we need the following:

  1. Wrapped objects of each word - to make sure there's no fragmentation of the word
  2. given width of each word.
  3. Partition the polygon into chunks that are the heights of the word. So you have x horizontal strips that make up the image.
  4. Then, find the width of the inside polygon if you were to inscribe words inside. This means you're removing the round edges of the heart. Where a vertical line can intersect the edge of the heart on the strip is where you remove the round edge.

Now that we have the size of each strip of the image, let's say we have this (i'm using arbitary unit for width):

[_________] [__________]  <-- 10 width (5 each)
  [__________________] <-- 9 width
    [_____________] <-- 7 width   
       [_______] <-- 5 width
         [___] <-- 3 width
          [_] <-- 2 width

EDIT: Just realized how ugly the heart is, my bad.

Now we need the size of each word, and insert them sequentially. Each block has x width, and each word object has y width. If y width > x width, we move to the next line and check there

considering we already have widths
while(image.hasNextChunk()){
    currentChunk = image.nextChunk();
    if(currentWord.width < currentChunk.width) //insert here and then change currentWord to nextWord
    ...
}

I think this is what you want, but I'm not completely sure. Let me know if this helped! :)

凉风有信 2024-09-12 18:41:18

对于一个简单的算法,我们假设您可以计算每个单词周围的边界框,并且您有一个带有要填充的形状蒙版的图像。

从图像蒙版的顶部向下扫描,直到找到与第一个单词一样长的线。看看是否可以将其向下延伸成边界框大小的矩形。如果是这样,请删除第一个单词。如果没有,继续扫。

删除一个单词后,看看是否可以将边界框扩展为(第一个框 + 第二个框 + 空间)的宽度和 max(第一个框,第二个框)的高度。如果是这样,请删除第二个词。如果不是,请将第一个单词从左到右置于适合图像蒙版(从左到右)的边界框内,从蒙版中删除该边界框,然后继续。

您可以通过坚持线条具有相同的基线(即使被形状打破)(例如穿过心脏顶部小块的线条)来使这稍微花哨一些;然后,您需要有一个备用的“继续沿此基线”条件。但上面的基本想法,使用图像蒙版来尝试将矩形放入其中,完成后将其删除,就可以完成这项工作。

(使用几何运算比这里描述的基于像素的运算更快,但是人们必须担心所有情况来弄清楚边界框如何适合任意多边形,并且这里解释起来有点长。)

For a simple algorithm, let's assume that you can compute a bounding box around each word, and that you have an image with a mask of the shape that you want to fill.

Sweep down from the top of the image mask until you find a line that is as long as the first word. See if you can extend it downward into a rectangle the size of the bounding box. If so, drop the first word there. If not, keep sweeping.

Once you drop a word, see if you can extend the bounding box to be the width of (first box + second box + space) and the height of max(first box,second box). If so, drop the second word there. If not, center the first word left-to-right within the bounding box that will fit within your image mask (left to right), remove that bounding box from the mask, and keep going.

You can make this slightly fancier by insisting that lines have the same baseline even if broken by the shape (e.g. lines across the top nubs of the heart); you then need to have an alternate "continue along this baseline" condition. But the basic idea above, with an image mask that you use to try to fit rectangles inside which are removed when you're done, will do the job.

(It is faster to use geometric operations than pixel-based ones described here, but then one has to worry about all the cases for figuring out how a bounding box fits within an arbitrary polygon, and that's a bit long to explain here.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文