Advertisement
Guest User

/Write FontHandler.cs

a guest
Oct 7th, 2012
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.82 KB | None | 0 0
  1. using System;
  2. using System.IO;
  3. using System.Collections.Generic;
  4. using System.Drawing;
  5. using System.Linq;
  6. using System.Text;
  7.  
  8. //Copyright (C) <2012> <Jon Baker, Glenn Mariën and Lao Tszy>
  9.  
  10. //This program is free software: you can redistribute it and/or modify
  11. //it under the terms of the GNU General Public License as published by
  12. //the Free Software Foundation, either version 3 of the License, or
  13. //(at your option) any later version.
  14.  
  15. //This program is distributed in the hope that it will be useful,
  16. //but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. //GNU General Public License for more details.
  19.  
  20. //You should have received a copy of the GNU General Public License
  21. //along with this program.  If not, see <http://www.gnu.org/licenses/>.
  22. namespace fCraft
  23. {
  24.     public class FontHandler
  25.     {
  26.         #region Instance and Drawing
  27.         public Player player; //player using command
  28.         public int blockCount; //blockcount for player message. ++ when drawing
  29.         int blocks = 0, //drawn blocks
  30.             blocksDenied = 0; //denied blocks (zones, ect)
  31.         fCraft.Drawing.UndoState undoState; //undostate
  32.         Direction direction; //direction of the blocks (x++-- ect)
  33.  
  34.         //instance
  35.         public FontHandler(Block textColor, Vector3I[] Marks, Player p, Direction dir)
  36.         {
  37.             direction = dir;
  38.             blockCount = 0;
  39.             player = p;
  40.             PixelData.X = Marks[0].X;
  41.             PixelData.Y = Marks[0].Y;
  42.             PixelData.Z = Marks[0].Z;
  43.             PixelData.BlockColor = textColor;
  44.             undoState = player.DrawBegin(null);
  45.         }
  46.  
  47.         public void CreateGraphicsAndDraw(string Sentence){
  48.             SizeF size = MeasureTextSize(Sentence, player.font); //measure the text size to create a bmp)
  49.             Bitmap img = new Bitmap((int)size.Width, (int)size.Height); //make an image based on string size
  50.             using (Graphics g = Graphics.FromImage(img)){ //IDisposable
  51.                 g.FillRectangle(Brushes.White, 0, 0, img.Width, img.Height); //make background, else crop will not work
  52.                 g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit; //fix to bleeding
  53.                 g.DrawString(Sentence, player.font, Brushes.Black, 0, 0); //draw some sexytext
  54.                 img = Crop(img); //crop the image to fix all problems with location
  55.                 img.RotateFlip(RotateFlipType.Rotate180FlipX); //flip this badboy
  56.                 Draw(img); //make the blockupdates
  57.                 img.Dispose(); //gtfo homeslice
  58.             }
  59.         }
  60.         public void Draw(Bitmap img){
  61.             //guess how big the draw will be
  62.             int Count = 0;
  63.             for (int x = 0; x < img.Width; x++){
  64.                 for (int z = 0; z < img.Height; z++){
  65.                     if (img.GetPixel(x, z).ToArgb() != System.Drawing.Color.White.ToArgb()){
  66.                         Count++;
  67.                     }
  68.                 }
  69.             }
  70.             //check if player can make the drawing
  71.             if (!player.CanDraw(Count)){
  72.                 player.MessageNow(String.Format("You are only allowed to run commands that affect up to {0} blocks. This one would affect {1} blocks.",
  73.                                                player.Info.Rank.DrawLimit, Count));
  74.                 return;
  75.             }
  76.             //check direction and draw
  77.             switch (direction){
  78.                 case Direction.one:
  79.                     for (int x = 0; x < img.Width; x++){
  80.                         for (int z = 0; z < img.Height; z++){
  81.                             if (img.GetPixel(x, z).ToArgb() != System.Drawing.Color.White.ToArgb()){
  82.                                 DrawOneBlock(player, player.World.Map, PixelData.BlockColor,
  83.                                       new Vector3I((PixelData.X + x), PixelData.Y, (PixelData.Z + z)), BlockChangeContext.Drawn,
  84.                                       ref blocks, ref blocksDenied, undoState);
  85.                                 blockCount++;
  86.                             }
  87.                         }
  88.                     }
  89.                     break;
  90.                 case Direction.two:
  91.                     for (int x = 0; x < img.Width; x++){
  92.                         for (int z = 0; z < img.Height; z++){
  93.                             if (img.GetPixel(x, z).ToArgb() != System.Drawing.Color.White.ToArgb()){
  94.                                 DrawOneBlock(player, player.World.Map, PixelData.BlockColor,
  95.                                       new Vector3I((PixelData.X - x), PixelData.Y, (PixelData.Z + z)), BlockChangeContext.Drawn,
  96.                                       ref blocks, ref blocksDenied, undoState);
  97.                                 blockCount++;
  98.                             }
  99.                         }
  100.                     }
  101.                     break;
  102.                 case Direction.three:
  103.                     for (int y = 0; y < img.Width; y++){
  104.                         for (int z = 0; z < img.Height; z++){
  105.                             if (img.GetPixel(y, z).ToArgb() != System.Drawing.Color.White.ToArgb()){
  106.                                 DrawOneBlock(player, player.World.Map, PixelData.BlockColor,
  107.                                       new Vector3I(PixelData.X, (PixelData.Y + y), (PixelData.Z + z)), BlockChangeContext.Drawn,
  108.                                       ref blocks, ref blocksDenied, undoState);
  109.                                 blockCount++;
  110.                             }
  111.                         }
  112.                     }
  113.                     break;
  114.                 case Direction.four:
  115.                     for (int y = 0; y < img.Width; y++){
  116.                         for (int z = 0; z < img.Height; z++){
  117.                             if (img.GetPixel(y, z).ToArgb() != System.Drawing.Color.White.ToArgb()){
  118.                                 DrawOneBlock(player, player.World.Map, PixelData.BlockColor,
  119.                                       new Vector3I(PixelData.X, ((PixelData.Y) - y), (PixelData.Z + z)), BlockChangeContext.Drawn,
  120.                                       ref blocks, ref blocksDenied, undoState);
  121.                                 blockCount++;
  122.                             }
  123.                         }
  124.                     }
  125.                     break;
  126.                 default:
  127.                     break; //if blockcount = 0, message is shown and returned
  128.             }
  129.         }
  130.         #endregion
  131.  
  132.         #region Helpers
  133.         public static Bitmap Crop(Bitmap bmp){
  134.             int w = bmp.Width;
  135.             int h = bmp.Height;
  136.             Func<int, bool> allWhiteRow = row =>{
  137.                 for (int i = 0; i < w; ++i)
  138.                     if (bmp.GetPixel(i, row).R != 255)
  139.                         return false;
  140.                 return true;
  141.             };
  142.             Func<int, bool> allWhiteColumn = col =>{
  143.                 for (int i = 0; i < h; ++i)
  144.                     if (bmp.GetPixel(col, i).R != 255)
  145.                         return false;
  146.                 return true;
  147.             };
  148.             int topmost = 0;
  149.             for (int row = 0; row < h; ++row){
  150.                 if (allWhiteRow(row))
  151.                     topmost = row;
  152.                 else break;
  153.             }
  154.             int bottommost = 0;
  155.             for (int row = h - 1; row >= 0; --row){
  156.                 if (allWhiteRow(row))
  157.                     bottommost = row;
  158.                 else break;
  159.             }
  160.             int leftmost = 0, rightmost = 0;
  161.             for (int col = 0; col < w; ++col){
  162.                 if (allWhiteColumn(col))
  163.                     leftmost = col;
  164.                 else
  165.                     break;
  166.             }
  167.             for (int col = w - 1; col >= 0; --col){
  168.                 if (allWhiteColumn(col))
  169.                     rightmost = col;
  170.                 else
  171.                     break;
  172.             }
  173.             if (rightmost == 0) rightmost = w; // As reached left
  174.             if (bottommost == 0) bottommost = h; // As reached top.
  175.             int croppedWidth = rightmost - leftmost;
  176.             int croppedHeight = bottommost - topmost;
  177.             if (croppedWidth == 0){// No border on left or right
  178.                 leftmost = 0;
  179.                 croppedWidth = w;
  180.             }
  181.             if (croppedHeight == 0){// No border on top or bottom
  182.                 topmost = 0;
  183.                 croppedHeight = h;
  184.             }try{
  185.                 var target = new Bitmap(croppedWidth, croppedHeight);
  186.                 using (Graphics g = Graphics.FromImage(target)){
  187.                     g.DrawImage(bmp,
  188.                       new RectangleF(0, 0, croppedWidth, croppedHeight),
  189.                       new RectangleF(leftmost, topmost, croppedWidth, croppedHeight),
  190.                       GraphicsUnit.Pixel);
  191.                 }
  192.                 return target;
  193.             }catch{
  194.                 return bmp; //return original image, I guess
  195.             }
  196.         }
  197.         //Measure the size of the string length using IDisposable. Backport from 800Craft Client
  198.         public static SizeF MeasureTextSize(string text, Font font){
  199.             using (Bitmap bmp = new Bitmap(1, 1)){
  200.                 using (Graphics g = Graphics.FromImage(bmp)){
  201.                     return g.MeasureString(text, font);
  202.                 }
  203.             }
  204.         }
  205.         //stores information needed for each pixel
  206.         public struct PixelData{
  207.             public static int X;
  208.             public static int Y;
  209.             public static int Z;
  210.             public static Block BlockColor;
  211.         }
  212.  
  213.         //stolen from BuildingCommands
  214.         #region DrawOneBlock
  215.         static void DrawOneBlock(Player player, Map map, Block drawBlock, Vector3I coord,
  216.                                  BlockChangeContext context, ref int blocks, ref int blocksDenied, fCraft.Drawing.UndoState undoState)
  217.         {
  218.             if (map == null) return;
  219.             if (player == null) throw new ArgumentNullException("player");
  220.  
  221.             if (!map.InBounds(coord)) return;
  222.             Block block = map.GetBlock(coord);
  223.             if (block == drawBlock) return;
  224.  
  225.             if (player.CanPlace(map, coord, drawBlock, context) != CanPlaceResult.Allowed)
  226.             {
  227.                 blocksDenied++;
  228.                 return;
  229.             }
  230.  
  231.             map.QueueUpdate(new BlockUpdate(null, coord, drawBlock));
  232.             Player.RaisePlayerPlacedBlockEvent(player, map, coord, block, drawBlock, context);
  233.  
  234.             if (!undoState.IsTooLargeToUndo)
  235.             {
  236.                 if (!undoState.Add(coord, block))
  237.                 {
  238.                     player.Message("NOTE: This draw command is too massive to undo.");
  239.                     player.LastDrawOp = null;
  240.                 }
  241.             }
  242.             blocks++;
  243.         }
  244.         #endregion
  245.         #endregion
  246.     }
  247. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement