/// <summary> /// 文字グリフからテクスチャを生成する /// </summary> /// <param name="layouter"></param> void ProcessTexture(BoxLayouter layouter) { // レイアウト、複数の矩形を1つの矩形内に並べる int width, height; layouter.Layout(out width, out height); // 配置後のグリフを画像へ書き込む var bitmap = new PixelBitmapContent <Color>(width, height); for (int i = 0; i < layouter.Items.Count; ++i) { // グリフ位置情報の追加 var rc = fontContent.Glyphs[i]; rc.X = layouter.Items[i].Bounds.X; rc.Y = layouter.Items[i].Bounds.Y; fontContent.Glyphs[i] = rc; // 個々のグリフ画像をひとつの画像へ追加する var pixels = layouter.Items[i].Tag as uint[]; int idx = 0; for (int y = 0; y < rc.Height; ++y) { for (int x = 0; x < rc.Width; ++x) { int r = (int)((pixels[idx] & 0x00ff0000) >> 16); int g = (int)((pixels[idx] & 0x0000ff00) >> 8); int b = (int)((pixels[idx] & 0x000000ff) >> 0); int a = (int)((pixels[idx] & 0xff000000) >> 24); bitmap.SetPixel(rc.X + x, rc.Y + y, new Color(r, g, b, a)); ++idx; } } } // 文字画像をまとめた画像をテクスチャへ変換する fontContent.Texture = new Texture2DContent(); switch (TextureFormat) { case WpfTextureFormat.Auto: if (UseGradient) { // グラデーション使用していればColorフォーマット fontContent.Texture.Mipmaps = bitmap; } else if (OutlineThickness > 0) { // アウトラインのみ使用していればBgra4444フォーマット fontContent.Texture.Mipmaps = bitmap; fontContent.Texture.ConvertBitmapType( typeof(PixelBitmapContent <Bgra4444>)); } else { // それ以外の単色フォントであれば単色に特化したDXT3圧縮をする fontContent.Texture.Mipmaps = SingleColorDxtCompressor.Compress(bitmap, FontColor); } break; case WpfTextureFormat.Bgra4444: fontContent.Texture.Mipmaps = bitmap; fontContent.Texture.ConvertBitmapType( typeof(PixelBitmapContent <Bgra4444>)); break; case WpfTextureFormat.Color: fontContent.Texture.Mipmaps = bitmap; break; } }
void ProcessGlyphs(ContentProcessorContext context) { // 文字描画に必要な情報設定 if (UseGradient) { textBrush = new LinearGradientBrush( ToWpfColor(this.GradientBeginColor), ToWpfColor(this.GradientEndColor), GradientAngle); } else { textBrush = new SolidColorBrush(ToWpfColor(FontColor)); } if (OutlineThickness > 0) { outlinePen = new Pen(new SolidColorBrush(ToWpfColor(OutlineColor)), OutlineThickness); outlinePen.LineJoin = OutlineShape; } else { outlinePen = null; } renderTarget = null; drawingVisual = new DrawingVisual(); // 登録文字をUnicode順に並び替える、これはXNAが実行時に文字グリフを // バイナリ検索しているので重要なステップ var characters = from c in input.Characters orderby c select c; var layouter = new BoxLayouter(); // 一文字ずつつ描画し、グリフ情報を生成する foreach (char c in characters) { // 文字描画 var glyphBounds = RenderCharacter(c); // ピクセル情報の取得 int stride = renderTarget.PixelWidth; uint[] pixels = new uint[stride * renderTarget.PixelHeight]; renderTarget.CopyPixels(pixels, stride * sizeof(uint), 0); // Black-Boxを取得し、必要な領域の画像イメージを取得 glyphBounds = NarrowerGlyph(pixels, stride, glyphBounds); var blackBox = GetBlackBox(pixels, stride, glyphBounds); pixels = new uint[blackBox.Width * blackBox.Height]; renderTarget.CopyPixels( ToInt32Rect(blackBox), pixels, blackBox.Width * sizeof(uint), 0); // カーニング情報の取得 var kerning = GetKerning(c, blackBox); // FontContentへの設定 fontContent.CharacterMap.Add(c); fontContent.Kerning.Add(kerning); fontContent.Glyphs.Add(new Rectangle( 0, 0, blackBox.Width, blackBox.Height)); fontContent.Cropping.Add(new Rectangle( blackBox.X - glyphBounds.X, blackBox.Y - glyphBounds.Y, glyphBounds.Width, glyphBounds.Height)); // レイアウト用アイテムとして追加 layouter.Add(new BoxLayoutItem { Bounds = blackBox, Tag = pixels }); } // テクスチャ処理 ProcessTexture(layouter); }