2.2.12 电子海图系统解析及开发 海图显示 - 符号化指令:显示文本

点、线、面物标都存在需要显示相关文本(如:物标名称)的情况。文本虽然不是符号库的一部分,但它却是电子海图数据的一部分。S-52标准规定,显示文本的字体只能是标准的“sans serif”。值得注意的是,水深点处的水深不是以文本方式出现,而是以符号的方式出现的。

为了阅读方便,电子海图显示文本时,一般不会旋转。文本的转心应该位于面物标的中心,或位于单个线段的中点,或位于多个线段的长度各的中心处。

文本显示涉及到两个命令:TXTE

1. TX 纯文本显示,不需要格式控制

纯文本显示命令

参数说明:

  • STRING  待显示的文本
         可传入固定文本,或物标的六字母属性(如:OBJNAM表示物标名称)。如果属性所对应的值为枚举或列表型,需要将其编号所代表的含义输出。
  • HJUST  水平对齐
         ’1‘ 表示居中
         ’2‘ 表示靠右
         ’3‘ 表示靠左(默认值)
  • VJUST  垂直对齐
         ’1‘ 表示靠下(默认值)
         ’2‘ 表示居中
         ’3‘ 表示靠上
  • SPACE  字符间距
         ’1‘ 两端对齐(调整字符间距,使文本填满物标的显示空间)
         ’2‘ 标准间距(默认值)
         ’3‘ 标准间距,但允许换行,单行字符不超过8个
  • CHARS  字符说明(字体,粗细、宽度(直体/斜体),字号等)
         字体
          ’1‘ 标准 sans serif (唯一选项)
         粗细
          ’4‘ 表示加细(对应值300)
          ’5‘ 表示中等(对应值500)
          ’6‘ 表示加粗(对应值700)
         宽度
          ’1‘ 表示直体,对于属性$CHARS的值,必须用直体表示
         字号
          单位为pica point(1 pica point = 0.351mm),最小值为10,同时也是默认值
  • XOFFS  x方向的偏移量
         单位为pica point,表示x方向上的偏移量,向右为正
  • YOFFS  y方向的偏移量
         单位为pica point,表示x方向上的偏移量,向下为正
  • COLOUR  文本的颜色
         用颜色标记指定的颜色
  • DISPLAY  文本的分组
         航海人员可按组选中文本

示例:TX(OBJNAM,1,2,3,’15110’,0,0,CHBLK,26)
含义:纯文本显示物标名称,水平居中,垂直居中,标准间距、允许换行,标准字体、加粗、直体、10号字,无偏移、颜色为CHBLK,组别为26。

2. TE 格式文本显示,其格式控制符合C语言标准

格式文本显示

与TX不同之处是,TE的文本显示是按照一定格式输出。该输出格式是符合C语言标准的,而本项目采用的C#编程,C#与C的格式控制是不兼容的,因此有两种方法解决:

  • 修改查询表中TE的格式控制字符串,使其满足C#标准,如: 将"clr cl %4.1lf"改为clr cl {0:f1}
  • 用C#编写工具类以实现C格式输出,有个现成的方案A printf implementation in C#。

示例:TE('clr cl %4.1lf','VERCCL',3,1,2,'15110',1,0,CHBLK,11)
含义:若物标属性VERCCL=16.2,最后显示的结果为:clr cl 16.2,其他含义与TX一样。

3. 编码实现

  • 对于TE指令,先将第一个参数(格式)和第二个参数内容读取出来,组合成纯文本,然后调用方法与TE一样。
    var txt = PrintFTools.sprintf("clr cl %4.1lf", 16.2); 
    
  • SPACE 字符间距
        1. 对于两端对齐方式,Skia并没有现成的现实方案。需要的流程较为复杂:计算物标的地理长度⇒屏幕长度⇒确定文本中单个字符的宽度⇒确定每个字符的绘制位置⇒依次绘制字符。考虑实际作用较小,而暂不考虑。
        2. 标准间距,对应SKFontStyleWidth.Normal
        3. 允许换行的标准间距,当文本长度超过8字符时,进行拆分,然后多行输出。考虑实际作用较小,而暂不考虑。
  • CHARS 字段编程
        字体 SKTypeface FromFamilyName("sans serif")
        粗细 4,5,6 对应SKFontStyleWeight中的LightNormalBold
        宽度 1,2对应SKFontStyleSlant中的UprightItalic
        字号 1 pica point = = 0.351mm = 96 / 25.4 * 0.351 像素
    //chars 形如 15110
    var fontWeight = SKFontStyleWeight.Normal;
    if (chars[1] == '4') fontWeight = SKFontStyleWeight.Light;
    else if (chars[1] == '6') fontWeight = SKFontStyleWeight.Bold;
    
    var fontSlant = SKFontStyleSlant.Upright;
    if (chars[2] != '1') fontSlant = SKFontStyleSlant.Italic;
    
    var textSize = PicaPoint * int.Parse(chars.Substring(3));
    
    var font = SKTypeface.FromFamilyName("sans serif", fontWeight, SKFontStyleWidth.Normal, fontSlant);
    var paint = new SKPaint(){ Typeface = font, TextSize = textSize };
    
  • COLOUR 字体颜色
    paint.Color = S52Colors.Instance[colour];
    
  • ** HJUST/VJUST** 对齐方式
        Skia文本的基点位于文本基线左侧,对于水平对齐可直接设置TextAlign,若要改变垂直对齐方式,需要获取字体信息,然后设置基点的位置。
    文本测量
    //水平对齐
    if (hjust == "2") paint.TextAlign = SKTextAlign.Right;
    else if(hjust == "1") paint.TextAlign = SKTextAlign.Center;
    //垂直对齐
    var fontMetrics = paint.FontMetrics;
    if (vjust == "3") y = y - fontMetrics.CapHeight; //Top:
    else if (hjust == "1") y = y - fontMetrics.CapHeight/2; //Center
    
  • XOFFS/YOFFS 偏移量
    if (xoffs != 0) x += PicaPoint * xoffs;
    if (yoffs != 0) y += PicaPoint * yoffs;
    

如果需要对文本进行理更为复杂的格式控制,可考虑使用第三方库RichTextKit,它是SkiaSharp的富文本布局,测量和渲染库。

  • 显示文本的完整代码如下:
    //字体大小单位 1 pica point = 0.351mm
    public const float PicaPoint = (float)MPP * 0.351f;

    //在屏幕指定坐标处绘制文本
    public static void DrawTextAtXY(SKCanvas ca, float x, float y, string txt,
        string hjust, string vjust, string space, string chars, int xoffs, int yoffs, string colour)
    {
        if (string.IsNullOrEmpty(txt)) return;

        //chars 形如 15110
        var fontWeight = SKFontStyleWeight.Normal;
        if (chars[1] == '4') fontWeight = SKFontStyleWeight.Light;
        else if (chars[1] == '6') fontWeight = SKFontStyleWeight.Bold;

        var fontSlant = SKFontStyleSlant.Upright;
        if (chars[2] != '1') fontSlant = SKFontStyleSlant.Italic;

        var textSize = PicaPoint * int.Parse(chars.Substring(3));

        var font = SKTypeface.FromFamilyName("sans serif", fontWeight, SKFontStyleWidth.Normal, fontSlant);
        var paint = new SKPaint() { Typeface = font, TextSize = textSize };

        //颜色
        paint.Color = S52Colors.Instance[colour];

        //水平对齐
        if (hjust == "2") paint.TextAlign = SKTextAlign.Right;
        else if (hjust == "1") paint.TextAlign = SKTextAlign.Center;

        var fontMetrics = paint.FontMetrics;
        if (vjust == "3") y = y - fontMetrics.CapHeight; //Top:
        else if (hjust == "1") y = y - fontMetrics.CapHeight / 2; //Center

        if (xoffs != 0) x += PicaPoint * xoffs;
        if (yoffs != 0) y += PicaPoint * yoffs;

        ca.DrawText(txt, x, y, paint);
    }
}

你可能感兴趣的:(2.2.12 电子海图系统解析及开发 海图显示 - 符号化指令:显示文本)