WYSIWYG与Unicode

时间:2010-08-16 21:21:02

标签: windows delphi unicode wysiwyg

我在Delphi中编写了一个Windows程序,它使用GetCharWidth和Em-Square非常精确地将文本放置到屏幕和打印机上。这适用于ANSI文本,您只需要检索和计算255个字符的宽度,但是当您使用65535个字符转到Unicode时,它太慢了。由于必须创建2个宽度数组,一个用于普通数组,一个用于粗体数组,因此问题变得更加严重。

 //Setup a reference canvas for measuring purposes
  RefDC := CreateCompatibleDC ( FCanvas.Handle ) ;
  DPI := GetDeviceCaps ( RefDC , LOGPIXELSY ) ;

  //find EmSquare
  GetOutlineTextMetrics ( RefDC , sizeof(otm) , @otm[0] ) ;
  EmSq := otm[0].otmEmSquare ;

  //calc NORMAL char sizes
  GetObject ( FCanvas.Font.Handle , SizeOf ( lf ) , @lf ) ;

  lf.lfHeight := -EmSq ;
  lf.lfWidth  := 0 ;
  lf.lfWeight   := FW_NORMAL ;

  hf := CreateFontIndirect ( lf ) ;
  hold := SelectObject ( RefDC , hf ) ;

  GetCharWidth ( RefDC , 0 , $FFFF , nCharWidth ) ;
  for a := 0 to $FFFF do
    fCharWidth[a] := nCharWidth[a]* PixelSize / EmSq ;

  SelectObject ( RefDC , hold ) ;
  DeleteObject ( hf ) ;

  //calculate line height
  PixelSize := abs ( fCanvas.Font.Size * DPI / 72 ) ;
  GetOutlineTextMetrics ( RefDC , sizeof(otm) , @otm[0] ) ;
  LineHt := round ( ( otm[0].otmTextMetrics.tmHeight +
                      otm[0].otmTextMetrics.tmExternalLeading ) *
                      PixelSize / EmSq ) ;

  //calculate Bold char sizes
  lf.lfWeight := FW_BOLD ;
  hf := CreateFontIndirect ( lf ) ;
  hold := SelectObject ( RefDC , hf ) ;

  GetCharWidth ( RefDC , 0 , $FFFF , nCharWidth ) ;
  for a := 0 to $FFFF do
    fBoldWidth[a] := nCharWidth[a] * PixelSize / EmSq ;

  SelectObject ( RefDC , hold ) ;
  DeleteObject ( hf ) ;

  DeleteDC ( RefDC ) ;`

4 个答案:

答案 0 :(得分:8)

计算单个字符宽度并以Unicode格式添加它们不仅非常慢,而且它是错误的并且无法正常工作。 Unicode将字符标记组合在一起,有时以复杂的方式组合。

使用Unicode,正确的方法是将整个字符串传递给Windows API函数GetTextExtentExPoint以及行的宽度,它将确定行的宽度是多少你。

an example of its use here

答案 1 :(得分:2)

我认为,在典型的会话中不太可能使用数千个字符。如果是这样,在第一轮中只计算前128个字符的宽度,并放入f.i.所有其余的-1。当进行查找时,测试宽度是否为-1,如果只是,则计算该字符的宽度,高度等。

答案 2 :(得分:1)

除了质疑问题本身的前提之外,你可以通过使用单独的数组和字体对象等获得两个nCharWidth数组并将它们一起处理,将你的两个0..65535循环减少到一个循环。

此外,您可以从循环中排除范围$ D800- $ DFFF,因为它们永远不能代表自己的字符(作为代理对中的第一个,您的代码似乎没有设计用来处理)。

答案 3 :(得分:0)

您是否使用过分析器实际查看瓶颈可能在哪里? 使用查找表时,一个常见的想法是,动态构建它们看起来成本太高,只需构建一次并将它们存储为资源...