2011-10-15 20 views
1

我正在尋找穩定的算法來繪製水平和垂直居中於2D表面的長文本。這不是特定於語言的,所以如果您可以用任何語言提供示例,這將非常有幫助。在2D表面繪製居中文本的算法

以下信息我有我想要繪製文本和表面:

文本資料:在PX(線高度)文本

  • 大小,當然是這樣大於表面
  • 類型表面的高度的情況下(可以是任何雖然)
  • 簡單的字符從ASCII32設置爲ASCII126
  • 文本可能是比較長的,也就是說由空格
  • 文本應打破「自動」的空格分開,一旦它不會在表面的寬度不合適了
  • 文字是英文。

表面信息:

  • 寬度和高度
  • x和y座標的全局座標系中(假定原點左屏幕的頂部角落)

我確實實現了我自己的方法,但它非常不穩定:文本散佈在曲面上,對齊不正確,有時根本不居中。也搜索一些好的方法,雖然找不到有用的東西。我希望stackoverflow社區可以幫助我。非常感謝你。

+0

你可以發佈你的方法嗎?瞭解什麼是丟棄會很有用。 – rendon

回答

1

該方法在概念上很簡單,有點涉及到執行。它只涉及幾個步驟:

Split the text into lines that will fit horizontally 
Compute the vertical position of the first line 
for each line 
    Compute its width and the X position 
    Display it at the Y position 
    Add the line height to the current Y position 

困難的部分是第一步。其餘的很容易。

如果你有一個固定寬度的字體,那麼把文本分成幾行並不難。您只需計算在給定寬度內適合的字符數量,將字符串索引到該位置,然後返回到前一個分詞符。從上一行的開頭(或第一行的字符串的開頭)抓取子字符串到該位置,這就是您的行。重複,直到到達字符串的末尾。

使用可變寬度字體時,事情會變得有點困難,因爲您不能只通過n * character_width字符索引字符串。相反,你必須猜測,測試,改進猜測等。我使用過的每個圖形子系統都有一些方法,它會告訴我在渲染一個字符串時需要多少像素,給定一個特定的字體。鑑於這種情況,我已經在過去做的是:

Divide the surface width by the font's average character width 
Index that far into the string, and find the next (or previous) word break. 
Measure the string 
If the result is wider than the width, go back one word and measure again. 
If the result is narrower than the width, go forward one word and measure again. 
Repeat the measure/adjust until you find the string that will fit. 

一旦找到,將適合,向前移動你的起始索引到下一行的開始,做一遍,直到你的子到達字符串的末尾。

垂直居中所述線羣組:

starting_position.Y = (Surface_height - (num_lines * line_height))/2 

平鋪爲中心的線很容易完成:

starting_position.X = (Surface_width - Measured_string_width)/2 

你必須計算starting_position.X對於每一行。對於每個連續的行,Y座標增加line_height

1

所以,你有一對夫婦的規律可循

  • 中心的每一行文字
  • ,如果一條線的長度>頁面寬度,開始新的一行
  • 垂直居中整個文本

所以你在空間上標記了你的輸入。您將需要一個字符串集合和一個currentIndex。雖然lines [currentIndex] + token.length < pageWidth,您可以向行[currentIndex]添加標記。一旦條件失敗,您將遞增currentIndex並繼續。

輸入完成後,您將每條線橫向居中。你必須計算每行的寬度,以像素爲單位。然後你做x = pageWidth/2 - lineWidth/2。

然後對文本塊高度進行相同的計算,但計算所有行(可能使用文本週圍的邊界矩形)。然後你可以用相同的公式獲得y值y = pageHeight/2 - textHeight/2

0

這是個人的方法。如果文本的長度不超過30個字符,並且空格之前的第一個單詞不超過15個字符,這將起作用。但是這個特性可以很容易地改變。文本將保存在2維數組中,如果一行不夠大,它將保存在2行。在以二維數組爲中心保存文本後,繪製它很簡單。我希望這會有所幫助。

char[][] t = new char[2][15]; 

public void putTextInMatrix(String text) { 
    int len = text.length(); 
    int start; 
    if(len<=15) { 
     start = (15-len)/2; 
     for (int i=0, j=0; i<15; i++) 
      if(i<start || i>=len+start) 
       t[0][i] = ' '; 
      else { 
       t[0][i] = text.charAt(j); 
       j++; 
      } 
    } 
    else { 
     int last = len; 
     for (int i=0; i<15; i++) { 
      if (text.charAt(i) == ' ') 
       last = i; 
     } 
     start = (15-last)/2; 
     for (int i=0, j=0; i<15; i++) 
      if(i<start || i>=last+start) 
       t[0][i] = ' '; 
      else { 
       t[0][i] = text.charAt(j); 
       j++; 
      } 

     start = (15-(len-last))/2; 
     for (int i=0, j=last+1; i<15; i++) 
      if(i<start || j>=len) 
       t[1][i] = ' '; 
      else { 
       t[1][i] = text.charAt(j); 
       j++; 
      } 
    } 
}