我是unicode的新手,所以我希望有人可以帮助我。我想将unicode写入PDF,现在我需要unicode文本的宽度和高度来进行文本格式化。对于AnsiString,我在PDF类中有这个功能:
function PDFClass.TextWidth(Text: AnsiString): Single;
var
i: integer;
ch: AnsiChar;
tmpWidth: Single;
chv: Integer;
begin
Result := 0;
for I := 1 to Length(Text) do
begin
ch := Text[i];
chv := CurrentFontObj.GetCharWidth(Text, I);
tmpWidth := chv * CurrentFontObj.Size / 1000;
if FHorizontalScaling <> 100 then
tmpWidth := tmpWidth * FHorizontalScaling / 100;
if tmpWidth > 0 then
tmpWidth := tmpWidth + FCharSpace
else
tmpWidth := 0;
if (ch = ' ') and (FWordSpace > 0) and (i <> Length(Text)) then
tmpWidth := tmpWidth + FWordSpace;
Result := Result + tmpWidth;
end;
Result := (Result / DocScale);
end;
function PDFClass.TextHeight(Text: AnsiString): Real;
begin
Result := CurrentFontObj.Size * CurrentFontObj.Ascent / 1000;
end;
任何人都可以帮我使用unicode文本的这个功能吗?我在带有UnicodeString的C ++ Builder 2009中使用了这个组件。
CurrentFontObj来自PDFFontObj类
PDFFontObj = class(TObject)
private
Name: AnsiString;
Size: Single;
ArrIndex: Integer;
Saved: boolean;
OldName: AnsiString;
Ascent: Integer;
FActive: boolean;
IsUsed: boolean;
UniLen: Integer;
FontLen: Integer;
IsUnicode: boolean;
IsVertical: boolean;
OrdinalName: AnsiString;
IsStandard: boolean;
FontStyle: TFontStyles;
FontCharset: TFontCharset;
IsMonospaced: boolean;
OutTextM: OUTLINETEXTMETRIC;
ABCArray: array[0..255] of ABC;
Symbols: array of CDescript;
UnicodeTable: array of IndexedChar;
SymbolTable: array[32..255] of boolean;
function GetCharWidth(AText: AnsiString; APos: integer): integer;
function GetCodeByID(ID: Word): Word;
procedure CopyFontFetures(InFnt: PDFFontObj);
procedure GetFontFeatures;
procedure ParseFontName;
procedure ClearTables;
end;
function PDFFontObj.GetCharWidth(AText: AnsiString; APos: integer): integer;
var
ChCode: Byte;
begin
ChCode := Ord(AText[APos]);
if not IsMonospaced then
Result := ABCArray[ChCode].abcA + Integer(ABCArray[ChCode].abcB) + ABCArray[ChCode].abcC
else
Result := ABCArray[0].abcA + Integer(ABCArray[0].abcB) + ABCArray[0].abcC;
end;
答案 0 :(得分:0)
在你写的评论中
我想连续写3个文本,每个文本用不同的颜色。为此,我需要每个文本的像素宽度。对于
AnsiString
,它是:
int width = PDF->CurrentPage->TextWidth(ansi_text);
但我需要Unicode文本的宽度,例如:
int width = PDF->CurrentPage->TextWidthUnicode(unicode_text_with_chinese_signs);
简答:
如果你的代码对Ansi字符串做了正确的事情,那么它应该可以正常使用Unicode而无需更改。
更长的回答:
PDFClass.TextWidth()
方法循环遍历字符串中的所有字符,调用当前字体对象的函数以获取单个字符的宽度,应用缩放并在字符和单词之间添加额外的空格。这或多或少是您在PDF 1.7 specification的第9章中可以阅读的内容。
您发布的代码不完整,但我怀疑它已经无法正常使用Ansi字符串。有Ansi编码可以使用多个字符来编码一个可见字符字形,即CJK多字节编码。循环Ansi字符串中的单个字节并总结返回的宽度在那里无法正常工作。代码可能会以某种方式解释此问题,但您的代码段不会显示它。
代码也可能存在不同的单字节Ansi编码问题,但很难从您发布的代码片段中分辨出来。如果您使用非ASCII字符(例如'ä'或'á')的Ansi程序并以例如俄语Windows版本运行它,创建的PDF文件是否包含西里尔字形?如果没有,则代码不会将必要的编码信息放入PDF中。如果是这样,那么它也无法用于Unicode字符串。有关编码问题的更多信息,请参阅PDF规范。
另请注意,即使编译代码,代码也可能不适用于所有用户:
您需要一个包含所有必需字形的字体(在您的示例中为中文)。如果没有,则会显示后备字形。如果系统不具有完全相同的字体,则可以使用类似但不同的字体,其可以对于一些或所有字形具有不同的宽度,在这种情况下,计算的宽度将是错误的。因此,最好在PDF文档中嵌入TrueType字体(甚至只使用字体中使用的字形)。 TTF字体可能是也可能不是可嵌入的,您可能没有权利嵌入它并分发文档。
有些语言会从右到左放置字形,甚至可以垂直堆叠。
有些语言会使用其他代码点来分隔单词,问题中的代码只将空格识别为单词分隔符。如果FWordSpace
不等于0,这将再次导致计算产生不同的结果。