テキストとグラフィックスの統合

Download Sampleサンプルのダウンロード

SkiaSharp グラフィックスとテキストを統合するためにレンダリングされたテキスト文字列のサイズを決定する方法を確認します

この記事では、テキストを測定し、テキストを特定のサイズにスケーリングし、テキストを他のグラフィックスと統合する方法について説明します。

Text surrounded by rectangles

この画像には、丸い四角形も含まれています。 SkiaSharp の Canvas クラスには、四角形を描画する DrawRect メソッドと、角が丸い四角形を描画する DrawRoundRect メソッドが含まれています。 これらのメソッドを使用すると、四角形を SKRect 値として、または別の方法で定義できます。

Framed Text ページでは、ページ上で短いテキスト文字列を中央揃えし、角が丸い四角形のペアで構成されたフレームでこれを囲みます。 FramedTextPage クラスは、その実行方法を示しています。

SkiaSharp では、SKPaint クラスを使用してテキスト属性とフォント属性を設定しますが、これを使用してレンダリングされたテキストのサイズを取得することもできます。 次の PaintSurface イベント ハンドラーの先頭では、2 つの異なる MeasureText メソッドを呼び出しています。 最初の MeasureText 呼び出しは単純な string 引数を持ち、現在のフォント属性に基づいてテキストのピクセル幅を返します。 このプログラムは次に、レンダリングされたその幅、現在の TextSize プロパティ、および表示領域の幅に基づいて、SKPaint オブジェクトの新しい TextSize プロパティを計算します。 この計算は、テキスト文字列が画面の幅の 90% でレンダリングされるように TextSize を設定することを意図しています。

void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
    SKImageInfo info = args.Info;
    SKSurface surface = args.Surface;
    SKCanvas canvas = surface.Canvas;

    canvas.Clear();

    string str = "Hello SkiaSharp!";

    // Create an SKPaint object to display the text
    SKPaint textPaint = new SKPaint
    {
        Color = SKColors.Chocolate
    };

    // Adjust TextSize property so text is 90% of screen width
    float textWidth = textPaint.MeasureText(str);
    textPaint.TextSize = 0.9f * info.Width * textPaint.TextSize / textWidth;

    // Find the text bounds
    SKRect textBounds = new SKRect();
    textPaint.MeasureText(str, ref textBounds);
    ...
}

2 番目の MeasureText 呼び出しには SKRect 引数があるため、レンダリングされたテキストの幅と高さの両方を取得します。 この SKRect 値の Height プロパティは、テキスト文字列に大文字、アセンダー、ディセンダーが存在するかどうかによって異なります。 たとえば、テキスト文字列 "mom"、"cat"、"dog" に対して異なる Height 値が報告されます。

レンダリングされたテキストが X 位置と Y 位置が 0 である DrawText 呼び出しによって表示される場合、SKRect 構造体の Left および Top プロパティは、このテキストの左上隅の座標を示します。 たとえば、このプログラムが iPhone 7 シミュレーターで実行されている場合、MeasureText に対する最初の呼び出しに続く計算の結果として TextSize に値 90.6254 が割り当てられます。 MeasureText に対する 2 番目の呼び出しから取得された SKRect 値には、次のプロパティ値があります。

  • Left = 6
  • Top = –68
  • Width = 664.8214
  • Height = 88;

DrawText メソッドに渡す X 座標と Y 座標は、ベースラインにあるテキストの左側を指定します。 Top 値は、テキストがそのベースラインより 68 ピクセル上、および (88 から 68 を減算して) ベースラインより 20 ピクセル下に拡張されることを示します。 Left 値の 6 は、DrawText 呼び出しでテキストが X 値の 6 ピクセル右側から始まることを示します。 これにより、通常の内部文字間隔が可能になります。 ディスプレイの左上隅にテキストをぴったりと表示するには、これらの Left および Top の負の値を DrawText の X 座標と Y 座標 (この例では –6 と 68) として渡します。

SKRect 構造体は、いくつかの便利なプロパティとメソッドを定義します。その一部は PaintSurface ハンドラーの残りの部分で使用されます。 MidX および MidY 値は、四角形の中心の座標を示します。 (iPhone 7 の例では、これらの値は 338.4107 と –24 です。)次のコードでは、これらの値を使用して、ディスプレイ上のテキストを中央揃えするための座標を最も簡単に計算します。

void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
    ...
    // Calculate offsets to center the text on the screen
    float xText = info.Width / 2 - textBounds.MidX;
    float yText = info.Height / 2 - textBounds.MidY;

    // And draw the text
    canvas.DrawText(str, xText, yText, textPaint);
    ...
}

SKImageInfo 情報構造ではタイプ SKRectRect プロパティも定義されるため、次のようにxTextyText を計算することもできます。

float xText = info.Rect.MidX - textBounds.MidX;
float yText = info.Rect.MidY - textBounds.MidY;

PaintSurface ハンドラーは DrawRoundRect に対する 2 回の呼び出しで終了します。これらは両方とも SKRect の引数を必要とします。 この SKRect 値は MeasureText メソッドから取得した SKRect 値に基づいていますが、同じにすることはできません。 最初に、この値を少し大きくし、角が丸い四角形がテキストの端に描画されないようにする必要があります。 次に、この値を空間内でシフトし、Left および Top 値が、四角形が配置される左上隅に対応するようにする必要があります。 これら 2 つのジョブは、SKRect によって定義された Offset および Inflate メソッドによって実行されます。

void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
    ...
    // Create a new SKRect object for the frame around the text
    SKRect frameRect = textBounds;
    frameRect.Offset(xText, yText);
    frameRect.Inflate(10, 10);

    // Create an SKPaint object to display the frame
    SKPaint framePaint = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        StrokeWidth = 5,
        Color = SKColors.Blue
    };

    // Draw one frame
    canvas.DrawRoundRect(frameRect, 20, 20, framePaint);

    // Inflate the frameRect and draw another
    frameRect.Inflate(10, 10);
    framePaint.Color = SKColors.DarkBlue;
    canvas.DrawRoundRect(frameRect, 30, 30, framePaint);
}

その後は、メソッドの残りの部分は単純明快です。 境界線用の別の SKPaint オブジェクトが作成され、DrawRoundRect が 2 回呼び出されます。 2 回目の呼び出しでは、別の 10 ピクセル分膨らんだ四角形が使用されます。 最初の呼び出しでは、20 ピクセルの角の半径が指定されます。 2 回目の呼び出しの角の半径は 30 ピクセルであるため、これらは平行に見えます。

Triple screenshot of the Framed Text page

スマートフォンやシミュレーターを横向きにして、テキストとフレームのサイズが大きくなることを確認できます。

画面上の一部のテキストのみを中央揃えする必要がある場合は、テキストを測定せずに概算で行うことができます。 代わりに、SKPaintTextAlign プロパティを、列挙型メンバー SKTextAlign.Center に設定します。 DrawText メソッドで指定する X 座標は、テキストの水平方向の中心がどこに配置されているかを示します。 画面の中間点を DrawText メソッドに渡すと、ベースラインが垂直方向に中央に配置されるため、テキストは、水平方向に中央に配置され、ベースラインが垂直方向に中央揃えされるためにほぼ垂直方向に中央揃えされます。

テキストは、その他のグラフィカル オブジェクトと同様に扱うことができます。 1 つの簡単なオプションは、テキスト文字の枠線を表示することです。

Triple screen shot of the Outlined Text page

これは、SKPaint オブジェクトの通常の Style プロパティを SKPaintStyle.Fill の既定の設定から SKPaintStyle.Stroke に変更し、ストロークの幅を指定するだけで実現できます。 Outlined Text ページの PaintSurface ハンドラーは、その実行方法を示しています。

void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
    SKImageInfo info = args.Info;
    SKSurface surface = args.Surface;
    SKCanvas canvas = surface.Canvas;

    canvas.Clear();

    string text = "OUTLINE";

    // Create an SKPaint object to display the text
    SKPaint textPaint = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        StrokeWidth = 1,
        FakeBoldText = true,
        Color = SKColors.Blue
    };

    // Adjust TextSize property so text is 95% of screen width
    float textWidth = textPaint.MeasureText(text);
    textPaint.TextSize = 0.95f * info.Width * textPaint.TextSize / textWidth;

    // Find the text bounds
    SKRect textBounds = new SKRect();
    textPaint.MeasureText(text, ref textBounds);

    // Calculate offsets to center the text on the screen
    float xText = info.Width / 2 - textBounds.MidX;
    float yText = info.Height / 2 - textBounds.MidY;

    // And draw the text
    canvas.DrawText(text, xText, yText, textPaint);
}

もう 1 つの一般的なグラフィカル オブジェクトはビットマップです。 これは SkiaSharp ビットマップのセクションで詳しく説明されている大きなトピックですが、次の記事である SkiaSharp のビットマップの基本で簡単に説明します。