1

2Dサーフェスの中央に水平方向および垂直方向に長いテキストを描画するための安定したアルゴリズムを探しています。これは言語固有ではないため、任意の言語で例を提供できれば非常に役立ちます。

描きたいテキストと表面について、次の情報があります。

テキスト情報:

  • テキストのサイズ(ピクセル単位)(行の高さ)は、もちろん表面の高さよりもはるかに小さいです
  • 書体(ただし、どのようなものでもかまいません)
  • ASCII32からASCII126までの単純な文字セット
  • テキストは比較的長くなる可能性があり、単語はスペースで区切られます
  • テキストが表面の幅に収まらなくなったら、テキストはスペースで「自動的に」途切れます。
  • テキストは英語です。

表面情報:

  • 幅と高さ
  • グローバル座標系のx座標とy座標(原点が画面の左上隅であると想定)

私は独自のアプローチを実装しましたが、それは非常に不安定でした。テキストが表面全体に広がり、配置が正しくなく、中央に配置されないこともありました。また、有用なものを見つけることができませんでしたが、いくつかの良いアプローチをグーグルで検索しました。stackoverflowコミュニティが私を助けてくれることを願っています。どうもありがとうございます。

4

3 に答える 3

2

このアプローチは概念が単純で、実行に少し関与しています。いくつかの手順のみが含まれます。

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_widthMeasureString代わりに、推測、テスト、推測の改良などを行う必要があります。私が使用したすべてのグラフィックス サブシステムには、特定のフォントを指定して、文字列をレンダリングするのに必要なピクセル数を教えてくれる何らかのメソッドがありました。それを考えると、私が過去に行ったことは次のとおりです。

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、連続する行ごとに増加します。

于 2011-10-15T04:35:00.463 に答える
1

したがって、従うべきいくつかのルールがあります

  • テキストのすべての行を中央揃え
  • 行の長さ > ページ幅の場合、新しい行を開始します
  • テキスト全体を垂直方向に中央揃えにする

したがって、スペースで入力をトークン化します。文字列のコレクションと currentIndex が必要です。lines[currentIndex] + token.length < pageWidth の間、lines[currentIndex] にトークンを追加できます。条件が満たされない場合は、currentIndex をインクリメントして続行します。

入力が終了したら、各行を水平方向に中央揃えにします。各線の幅をピクセル単位で計算する必要があります。次に、x = pageWidth/2 - lineWidth/2 を実行します。

次に、テキスト ブロックの高さについて同じ計算を行いますが、すべての行を考慮します (テキストの周囲に外接する四角形を使用することもできます)。次に、同じ式 y = pageHeight/2 - textHeight /2 で y 値を取得できます。

于 2011-10-15T04:29:13.107 に答える
0

これは個人的なアプローチです。これは、テキストの長さが 30 文字以下で、スペースの前の最初の単語が 15 文字より長くない場合に機能します。ただし、この特性は非常に簡単に変更できます。テキストは 2 次元配列で保存され、1 行が十分に大きくない場合は 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++;
            }
    }
}
于 2012-07-05T16:50:13.080 に答える