type
PABC = ^ABCarray;
ABCarray = array [0..255] of ABC;
function ReverseString(const AText: string): string;
var
I: Integer;
P: PChar;
begin
SetLength(Result, Length(AText));
P := PChar(Result);
for I := Length(AText) downto 1 do
begin
P^ := AText;
Inc(P);
end;
end;
procedure TfrxPDFFile.Clear;
var
i: Integer;
begin
for i := 0 to FPages.Count - 1 do
begin
TfrxPDFPage(FPages).Free;
end;
FPages.Clear;
for i := 0 to FFonts.Count - 1 do
TfrxPDFFont(FFonts).Free;
FFonts.Clear;
FXRef.Clear;
end;
function DoCalcOutlineCount: Integer;
var
i: Integer;
begin
Result := FPreviewOutline.Count;
for i := 0 to FPreviewOutline.Count - 1 do
begin
FPreviewOutline.LevelDown(i);
Result := Result + DoCalcOutlineCount;
FPreviewOutline.LevelUp;
end;
end;
procedure DoPrepareOutline(Node: TfrxPDFOutlineNode);
var
i: Integer;
cnt: Integer;
p: TfrxPDFOutlineNode;
prev: TfrxPDFOutlineNode;
begin
cnt := FPreviewOutline.Count;
Node.Count := cnt;
Node.CountTree := cnt;
Inc(NodeNumber);
prev := nil;
p := nil;
for i := 0 to cnt - 1 do
begin
p := TfrxPDFOutlineNode.Create;
FPreviewOutline.GetItem(i, Text, Page, Top);
p.Title := Text;
p.Dest := Page;
p.Top := Top;
p.Prev := prev;
if prev <> nil then
prev.Next := p
else
Node.First := p;
prev := p;
p.Parent := Node;
FPreviewOutline.LevelDown(i);
DoPrepareOutline(p);
FPreviewOutline.LevelUp;
Node.CountTree := Node.CountTree + p.CountTree;
end;
Node.Last := p;
end;
procedure DoWriteOutline(Node: TfrxPDFOutlineNode; Parent: Integer);
var
p: TfrxPDFOutlineNode;
begin
p := Node;
if p.Dest = -1 then
begin
p.Number := Parent;
end
else begin
p.Number := FCounter;
XRefAdd(Stream);
WriteLn(Stream, IntToStr(FCounter) + ' 0 obj');
Inc(FCounter);
WriteLn(Stream, '<<');
WriteLn(Stream, '/Title (' + PTool.PrepareString(p.Title) + ')');
WriteLn(Stream, '/Parent ' + IntToStr(Parent) + ' 0 R');
if p.Prev <> nil then
WriteLn(Stream, '/Prev ' + IntToStr(p.Prev.Number) + ' 0 R');
if p.First <> nil then
begin
WriteLn(Stream, '/First ' + IntToStr(p.Number + 1) + ' 0 R');
WriteLn(Stream, '/Last ' + IntToStr(p.Number + p.CountTree - p.Last.CountTree ) + ' 0 R');
WriteLn(Stream, '/Count ' + IntToStr(p.Count));
end;
if p.Next <> nil then
WriteLn(Stream, '/Next ' + IntToStr(p.Number + p.CountTree + 1) + ' 0 R');
WriteLn(Stream, '/Dest [' + IntToStr(FpagesRoot + FFonts.Count * FFontDCnt + p.Dest * 2 + 1) + ' 0 R /XYZ 0 ' + IntToStr(Round(TfrxPDFPage(FPages[Page]).Height - p.Top * PDF_DIVIDER)) + ' 0]');
WriteLn(Stream, '>>');
WriteLn(Stream, 'endobj');
end;
if p.First <> nil then
DoWriteOutline(p.First, p.Number);
if p.Next <> nil then
DoWriteOutline(p.Next, Parent);
end;
begin
inherited SaveToStream(Stream);
OutlineCount := 0;
OutlineTree := nil;
if FOutline then
if not Assigned(FPreviewOutline) then
FOutline := False
else
FPreviewOutline.LevelRoot;
FCounter := 1;
s := FormatDateTime('yyyy', Now) + FormatDateTime('mm', Now) +
FormatDateTime('dd', Now) + FormatDateTime('hh', Now) +
FormatDateTime('nn', Now) + FormatDateTime('ss', Now);
WriteLn(Stream, '%PDF-' + PDF_VER);
WriteLn(Stream, '%'#226#227#207#211);
XRefAdd(Stream);
WriteLn(Stream, IntToStr(FCounter) + ' 0 obj');
Inc(FCounter);
WriteLn(Stream, '<<');
WriteLn(Stream, '/Type /Catalog');
i := 0;
if FOutline then
begin
OutlineTree := TfrxPDFOutlineNode.Create;
NodeNumber := 0;
DoPrepareOutline(OutlineTree);
OutlineCount := OutlineTree.CountTree - OutlineTree.Last.CountTree;
i := OutlineTree.CountTree + 1;
end;
function TfrxPDFFile.AddFont(Font: TFont): Integer;
var
Font2: TfrxPDFFont;
i, j: Integer;
begin
j := -1;
for i := 0 to FFonts.Count - 1 do
begin
Font2 := TfrxPDFFont(FFonts);
if (Font2.Font.Name = Font.Name) and
(Font2.Font.Style = Font.Style) and
(Font2.Font.Charset = Font.Charset) then
begin
j := i;
break;
end;
end;
if j = -1 then
begin
Font2 := TfrxPDFFont.Create;
Font2.Parent := Self;
Font2.Font.Assign(Font);
FFonts.Add(Font2);
j := FFonts.Count - 1;
Font2.Index := j * FFontDCnt + 1
end;
Result := j;
end;
function TfrxPDFFile.AddPage(Page: TfrxReportPage): TfrxPDFPage;
var
PDFPage: TfrxPDFPage;
begin
PDFPage := TfrxPDFPage.Create;
PDFPage.Width := Page.Width * PDF_DIVIDER;
PDFPage.Height := Page.Height * PDF_DIVIDER;
PDFPage.MarginLeft := Page.LeftMargin * PDF_MARG_DIVIDER;
PDFPAge.MarginTop := Page.TopMargin * PDF_MARG_DIVIDER;
PDFPage.Parent := Self;
PDFPage.OutStream := FStreamObjects;
PDFPage.StreamOffset := FStreamObjects.Position;
if FPages.Count > 0 then
TfrxPDFPage(FPages[FPages.Count - 1]).StreamSize := FStreamObjects.Position - TfrxPDFPage(FPages[FPages.Count - 1]).StreamOffset;
FPages.Add(PDFPage);
PDFPage.Index := FPages.Count;
Result := PDFPage;
if FEmbedded then
FFontDCnt := 3
else FFontDCnt := 2;
end;
procedure MakeUpFrames;
begin
if (Obj.Frame.Typ <> []) and (Obj.Frame.Color <> clNone) then
begin
WriteLn(OutStream, Parent.PTool.GetPDFColor(Obj.Frame.Color) + ' RG');
WriteLn(OutStream, Format('%.4f', [Obj.Frame.Width * PDF_DIVIDER]) + ' w');
if ftTop in Obj.Frame.Typ then
begin
WriteLn(OutStream, Format('%.4f', [GetLeft(Obj.AbsLeft)]) + ' ' + Format('%.4f', [GetTop(Obj.AbsTop)]) + ' m');
WriteLn(OutStream, Format('%.4f', [GetLeft(Obj.AbsLeft + Obj.Width)]) + ' ' + Format('%.4f', [GetTop(Obj.AbsTop)]) + ' l');
WriteLn(OutStream, 'S')
end;
if ftLeft in Obj.Frame.Typ then
begin
WriteLn(OutStream, Format('%.4f', [GetLeft(Obj.AbsLeft)]) + ' ' + Format('%.4f', [GetTop(Obj.AbsTop)]) + ' m');
WriteLn(OutStream, Format('%.4f', [GetLeft(Obj.AbsLeft)]) + ' ' + Format('%.4f', [GetTop(Obj.AbsTop + Obj.Height)]) + ' l');
WriteLn(OutStream, 'S')
end;
if ftBottom in Obj.Frame.Typ then
begin
WriteLn(OutStream, Format('%.4f', [GetLeft(Obj.AbsLeft)]) + ' ' + Format('%.4f', [GetTop(Obj.AbsTop + Obj.Height)]) + ' m');
WriteLn(OutStream, Format('%.4f', [GetLeft(Obj.AbsLeft + Obj.Width)]) + ' ' + Format('%.4f', [GetTop(Obj.AbsTop + Obj.Height)]) + ' l');
WriteLn(OutStream, 'S')
end;
if ftRight in Obj.Frame.Typ then
begin
WriteLn(OutStream, Format('%.4f', [GetLeft(Obj.AbsLeft + Obj.Width)]) + ' ' + Format('%.4f', [GetTop(Obj.AbsTop)]) + ' m');
WriteLn(OutStream, Format('%.4f', [GetLeft(Obj.AbsLeft + Obj.Width)]) + ' ' + Format('%.4f', [GetTop(Obj.AbsTop + Obj.Height)]) + ' l');
WriteLn(OutStream, 'S')
end;
end;
end;
function CheckhasDouble(s: string):boolean;
var
i: Integer;
begin
result:=false;
for i := 1 to Length(s) do
if ByteType(s, i) <> mbSingleByte then
begin
result := true;
Break;
end;
end;
function StrToHex(s: string): string;
var
i: integer;
begin
result := '';
for i := 1 to Length(s) do
result := result + IntToHex(ord(s), 2);
end;
function EscapeText(Value: string): string;
const
EscapeChars = ['(',')','/'];
var
i: integer;
begin
result := '';
for i := 1 to Length(Value) do
begin
if (Value in EscapeChars) and (ByteType(Value, i - 1) = mbSingleByte) then
result := result + '/' + Value
else
result := result + Value;
end;
end;
function InternalTextOut(s: string):String;
var
HasDoubleByteChar: boolean;
begin
HasDoubleByteChar := CheckhasDouble(S);
if HasDoubleByteChar then
begin
result := '<' + StrToHex(S) + '> Tj'
end
else
begin
result := '(' + EscapeText(S) + ') Tj';
end;
end;
function HTMLTags(View: TfrxCustomMemoView): Boolean;
var
f: Boolean;
begin
f := View.AllowHTMLTags;
View.AllowHTMLTags := True;
Result := FParent.HTMLTags and
(Pos('<' ,View.Memo.Text) > 0) and
(Pos('>' ,View.Memo.Text) > 0);
View.AllowHTMLTags := f;
end;
begin
OldSep := DecimalSeparator;
OldFrameWidth := 0;
DecimalSeparator := '.';
// save clip to stack
WriteLn(OutStream, 'q');
// set clipping path for the memo
Write(OutStream, Format('%.4f', [GetLeft(Obj.AbsLeft)]) + ' ' + Format('%.4f', [GetTop(Obj.AbsTop + Obj.Height)]) + ' ');
WriteLn(OutStream, Format('%.4f', [Obj.Width * PDF_DIVIDER]) + ' ' + Format('%.4f', [Obj.Height * PDF_DIVIDER]) + ' re');
WriteLn(OutStream, 'W');
WriteLn(OutStream, 'n');
// Text
if (Obj is TfrxCustomMemoView) and (TfrxCustomMemoView(Obj).Rotation = 0) and
(TfrxCustomMemoView(Obj).BrushStyle in [bsSolid, bsClear]) and
(not HTMLTags(TfrxCustomMemoView(Obj))) then
begin
// Shadow
if Obj.Frame.DropShadow then
begin
Obj.Width := Obj.Width - Obj.Frame.ShadowWidth;
Obj.Height := Obj.Height - Obj.Frame.ShadowWidth;
WriteLn(OutStream, Parent.PTool.GetPDFColor(Obj.Frame.ShadowColor) + ' rg');
WriteLn(OutStream, Parent.PTool.GetPDFColor(Obj.Frame.ShadowColor) + ' RG');
Write(OutStream, Format('%.4f', [GetLeft(Obj.AbsLeft + Obj.Width)]) + ' ' + Format('%.4f', [GetTop(Obj.AbsTop + Obj.Height + Obj.Frame.ShadowWidth)]) + ' ');
WriteLn(OutStream, Format('%.4f', [Obj.Frame.ShadowWidth * PDF_DIVIDER]) + ' ' + Format('%.4f', [Obj.Height * PDF_DIVIDER]) + ' re');
WriteLn(OutStream, 'B');
Write(OutStream, Format('%.4f', [GetLeft(Obj.AbsLeft + Obj.Frame.ShadowWidth)]) + ' ' + Format('%.4f', [GetTop(Obj.AbsTop + Obj.Height + Obj.Frame.ShadowWidth)]) + ' ');
WriteLn(OutStream, Format('%.4f', [Obj.Width * PDF_DIVIDER]) + ' ' + Format('%.4f', [Obj.Frame.ShadowWidth * PDF_DIVIDER]) + ' re');
WriteLn(OutStream, 'B');
end;
if TfrxCustomMemoView(Obj).Highlight.Active and
Assigned(TfrxCustomMemoView(Obj).Highlight.Font) then
begin
Obj.Font.Assign(TfrxCustomMemoView(Obj).Highlight.Font);
Obj.Color := TfrxCustomMemoView(Obj).Highlight.Color;
end;
if Obj.Color <> clNone then
begin
WriteLn(OutStream, Parent.PTool.GetPDFColor(Obj.Color) + ' rg');
Write(OutStream, Format('%.4f', [GetLeft(Obj.AbsLeft)]) + ' ' + Format('%.4f', [GetTop(Obj.AbsTop + Obj.Height)]) + ' ');
WriteLn(OutStream, Format('%.4f', [Obj.Width * PDF_DIVIDER]) + ' ' + Format('%.4f', [Obj.Height * PDF_DIVIDER]) + ' re');
WriteLn(OutStream, 'f');
end;
// Frames
MakeUpFrames;
Lines := TStringList.Create;
Lines.Text := TfrxCustomMemoView(Obj).WrapText(True);
if Lines.Count > 0 then
begin
try //夏
AFont:=Obj.Font;
AB := TBitmap.Create;
AB.Canvas.Font.Assign(AFont);
i := GetOutlineTextMetrics(AB.Canvas.Handle, 0, nil);
GetMem(pm, i);
GetOutlineTextMetrics(AB.Canvas.Handle, i, pm);
ACharset := pm.otmTextMetrics.tmCharSet;
HasDouble:=false;
for i := 0 to Lines.Count - 1 do
begin
s := Parent.PTool.TruncReturns(Lines);
HasDouble:=CheckhasDouble(S);
if HasDouble=true then
begin
break;
end;
end; // for
if HasDouble=true then
begin
if not (ACharset in [136,134]) then
begin
AFont.Name:='宋体';
AFont.Size:=Obj.Font.Size;
AFont.Color:=Obj.Font.Color;
end;
end;
finally
AB.Free;
end; // try/finally
FontIndex := Parent.AddFont(Obj.Font);
WriteLn(OutStream, '/F' + IntToStr(TfrxPDFFont(Parent.FFonts[FontIndex]).Index - 1) + ' ' + IntToStr(Obj.Font.Size) + ' Tf');
WriteLn(OutStream, Parent.PTool.GetPDFColor(Obj.Font.Color) + ' rg');
Parent.PTool.SetMemo(TfrxCustomMemoView(Obj));
// output lines of memo
for i := 0 to Lines.Count - 1 do
begin
if TfrxCustomMemoView(Obj).RTLReading then
s := Parent.PTool.Str2RTL(Parent.PTool.TruncReturns(Lines))
else
s := Parent.PTool.TruncReturns(Lines);
if Length(Trim(s)) > 0 then
begin
// Text output
WriteLn(OutStream, 'BT');
x := GetLeft(Parent.PTool.GetHTextPos(Obj.AbsLeft + TfrxCustomMemoView(Obj).GapX, Obj.Width - TfrxCustomMemoView(Obj).GapX * 2, Lines, TfrxCustomMemoView(Obj).HAlign));
y := GetTop(Parent.PTool.GetVTextPos(Obj.AbsTop + TfrxCustomMemoView(Obj).GapY - 2, Obj.Height - TfrxCustomMemoView(Obj).GapY * 2, Lines, TfrxCustomMemoView(Obj).VAlign, i, Lines.Count));
WriteLn(OutStream, Format('%.4f', [x]) + ' ' + Format('%.4f', [y]) + ' Td');
S:=InternalTextOut(S); //夏
WriteLn(OutStream, s);
WriteLn(OutStream, 'ET');
// set Underline
if fsUnderline in (TfrxCustomMemoView(Obj).Font.Style) then
begin
WriteLn(OutStream, Parent.PTool.GetPDFColor(Obj.Font.Color) + ' RG');
WriteLn(OutStream, Format('%.4f', [Obj.Font.Size * 0.08]) + ' w');
WriteLn(OutStream, Format('%.4f', [x]) + ' ' + Format('%.4f', [y - Obj.Font.Size * 0.12]) + ' m');
WriteLn(OutStream, Format('%.4f', [x + Parent.PTool.GetLineWidth(Lines) * PDF_DIVIDER]) + ' ' + Format('%.4f', [y - Obj.Font.Size * 0.12]) + ' l');
WriteLn(OutStream, 'S')
end;
end;
end;
end;
Lines.Free;
end
// Lines
else if Obj is TfrxCustomLineView then
begin
WriteLn(OutStream, Parent.PTool.GetPDFColor(Obj.Frame.Color) + ' RG');
WriteLn(OutStream, Format('%.4f', [Obj.Frame.Width * PDF_DIVIDER]) + ' w');
WriteLn(OutStream, Format('%.4f', [GetLeft(Obj.AbsLeft)]) + ' ' + Format('%.4f', [GetTop(Obj.AbsTop)]) + ' m');
WriteLn(OutStream, Format('%.4f', [GetLeft(Obj.AbsLeft + Obj.Width)]) + ' ' + Format('%.4f', [GetTop(Obj.AbsTop + Obj.Height)]) + ' l');
WriteLn(OutStream, 'S')
end
// Rects
else if (Obj is TfrxShapeView) and (TfrxShapeView(Obj).Shape = skRectangle) then
begin
WriteLn(OutStream, Parent.PTool.GetPDFColor(Obj.Frame.Color) + ' RG');
WriteLn(OutStream, Format('%.4f', [Obj.Frame.Width * PDF_DIVIDER]) + ' w');
WriteLn(OutStream, Parent.PTool.GetPDFColor(Obj.Color) + ' rg');
Write(OutStream, Format('%.4f', [GetLeft(Obj.AbsLeft)]) + ' ' + Format('%.4f', [GetTop(Obj.AbsTop + Obj.Height)]) + ' ');
WriteLn(OutStream, Format('%.4f', [Obj.Width * PDF_DIVIDER]) + ' ' + Format('%.4f', [Obj.Height * PDF_DIVIDER]) + ' re');
WriteLn(OutStream, 'B');
end
else
// Bitmaps
if not (((Obj.Name = '_pagebackground'){ or (Obj.Name = '')}) and (not Parent.Background)) then
begin
if Obj.Frame.Width > 0 then
begin
OldFrameWidth := Obj.Frame.Width;
Obj.Frame.Width := 0;
end;
TempBitmap := TBitmap.Create;
TempBitmap.PixelFormat := pf24bit;
if Parent.PrintOptimized or (Obj is TfrxCustomMemoView) then
i := PDF_PRINTOPT
else i := 1;
TempBitmap.Width := Round(Obj.Width * i) + 1;
TempBitmap.Height := Round(Obj.Height * i) + 1;
Obj.Draw(TempBitmap.Canvas, i, i, -Obj.AbsLeft * i, -Obj.AbsTop * i);
WriteLn(OutStream, 'q');
WriteLn(OutStream, Format('%.4f', [Obj.Width * PDF_DIVIDER]) +
' 0 0 ' + Format('%.4f', [Obj.Height * PDF_DIVIDER]) + ' ' +
Format('%.4f', [GetLeft(Obj.AbsLeft)]) + ' ' +
Format('%.4f', [GetTop(Obj.AbsTop + Obj.Height)]) + ' cm');
WriteLn(OutStream, 'BI');
WriteLn(OutStream, '/W ' + IntToStr(TempBitmap.Width));
WriteLn(OutStream, '/H ' + IntToStr(TempBitmap.Height));
WriteLn(OutStream, '/CS /RGB');
WriteLn(OutStream, '/BPC 8');
WriteLn(OutStream, '/I true');
WriteLn(OutStream, '/F [/DCT]');
WriteLn(OutStream, 'ID');
// support DBCS font name encoding
function EncodeFontName(AFontName: String): string;
var
s: string;
Index, Len: Integer;
begin
s := '';
Len := Length(AFontName);
Index := 0;
while Index < Len do
begin
Index := Index + 1;
if Byte(AFontName[Index]) > $7F then
s := s + '#' + IntToHex(Byte(AFontName[Index]), 2)
else
s := s + AFontname[Index];
end;
Result := s;
end;
function WriteFontToStream(ABT: TBitmap):string;
var
i: Integer;
pfontointer;
AStringStream:TStringStream;
begin
i := GetFontData(ABT.Canvas.Handle, 0, 0, nil, 1);
GetMem(pfont,i);
i := GetFontData(ABT.Canvas.Handle, 0, 0, pfont, i);
AStringStream:=TStringStream.Create('');
AStringStream.Write(pfont^,I);
result:=AStringStream.DataString;
AStringStream.Free;
FreeMem(pfont);
end;
begin
inherited SaveToStream(Stream);
b := TBitmap.Create;
b.Canvas.Font.Assign(Font);
b.Canvas.Font.PixelsPerInch := 96;
b.Canvas.Font.Size := 750;
i := GetOutlineTextMetrics(b.Canvas.Handle, 0, nil);
GetMem(pm, i);
try
try
GetOutlineTextMetrics(b.Canvas.Handle, i, pm);
FirstChar := Ord(pm.otmTextMetrics.tmFirstChar);
LastChar := Ord(pm.otmTextMetrics.tmLastChar);
FontName := StringReplace(Font.Name, ' ', '#20', [rfReplaceAll]);
s := '';
if fsBold in Font.Style then
s := s + 'Bold';
if fsItalic in Font.Style then
s := s + 'Italic';
if s <> '' then
FontName := FontName + ',' + s;
Charset := pm.otmTextMetrics.tmCharSet;
if (Charset = CHINESEBIG5_CHARSET)
or (Charset = 134)
then
FontName := EncodeFontName(FontName)
else
FontName := Parent.PTool.PrepareString(FontName);
constructor TfrxPDFToolkit.Create;
begin
Locale := GetLocaleInformation(LOCALE_SISO639LANGNAME);
Prefix := UnicodePrefix;
end;
function TfrxPDFToolkit.GetLocaleInformation(Flag: Integer): String;
var
pcLCA: array[0..20] of Char;
begin
if (GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, Flag, pcLCA,19) <= 0 ) then
pcLCA[0] := #0;
Result := pcLCA;
end;
function TfrxPDFToolkit.PrepareString(const Text: String): String;
begin
if CheckOEM(Text) then
Result := StrToOct(Prefix) + StrToOctUTF16(Text)
else
Result := Text;
end;
function TfrxPDFToolkit.GetHTextPos(Left: Extended; Width: Extended; const Text: String;
Align: TfrxHAlign): Extended;
var
FWidth: Extended;
begin
if (Align = haLeft) or (Align = haBlock) then
Result := Left
else begin
FWidth := GetLineWidth(Text);
if Align = haCenter then
Result := Left + Width / 2 - FWidth / 2
else
Result := Left + Width - FWidth;
end;
end;
function TfrxPDFToolkit.GetLineWidth(const Text: String): Extended;
var
FWidth: Extended;
begin
frxDrawText.Lock;
try
FWidth := frxDrawText.Canvas.TextWidth(Text) / (frxDrawText.DefPPI / frxDrawText.ScrPPI);
finally
frxDrawText.UnLock;
end;
Result := FWidth;
end;
function TfrxPDFToolkit.GetVTextPos(Top: Extended; Height: Extended; const Text: String;
Align: TfrxVAlign; Line: Integer = 0; Count: Integer = 1): Extended;
var
i: Integer;
begin
if Line <= Count then
i := Line
else
i := 0;
if Align = vaBottom then
Result := Top + Height - LineHeight * (Count - i - 1)
else if Align = vaCenter then
Result := Top + Height / 2 - (LineHeight * Count) / 2 + LineHeight * (i + 1)
else
Result := Top + LineHeight * (i + 1);
end;
function TfrxPDFToolkit.TruncReturns(Str: string): string;
begin
Str := StringReplace(Str, '/', '//', [rfReplaceAll]);
Str := StringReplace(Str, '(', '/(', [rfReplaceAll]);
Str := StringReplace(Str, ')', '/)', [rfReplaceAll]);
Str := StringReplace(Str, #1, '', [rfReplaceAll]);
if Copy(Str, Length(Str) - 1, 2) = #13#10 then
Delete(Str, Length(Str) - 1, 2);
Result := Str;
end;
function TfrxPDFToolkit.UnicodePrefix: String;
begin
Result := #254#255#0#27 + Locale + #0#27;
end;
function TfrxPDFToolkit.GetPDFColor(Color: TColor): String;
var
TheRgbValue : TColorRef;
OldSep: Char;
begin
TheRgbValue := ColorToRGB(Color);
OldSep := DecimalSeparator;
DecimalSeparator := '.';
Result := Format('%.2g %.2g %.2g', [GetRValue(TheRGBValue) / 255, GetGValue(TheRGBValue) / 255, GetBValue(TheRGBValue) / 255]);
DecimalSeparator := OldSep;
end;
function TfrxPDFToolkit.CheckOEM(const Value: String): boolean;
var
i: integer;
begin
result := false;
for i := 1 to Length(Value) do
if (ByteType(Value, i) <> mbSingleByte) or
(Ord(Value) > 122) or
(Ord(Value) < 32) then
begin
result := true;
Break;
end;
end;
function TfrxPDFToolkit.StrToOctUTF16(const Value: String): String;
var
PW: Pointer;
PByte: ^Byte;
HiByte, LoByte: Byte;
Len: integer;
i: integer;
begin
result := '';
Len := MultiByteToWideChar(0, CP_ACP, PChar(Value), Length(Value), nil, 0);
GetMem(PW, Len * 2);
Len := MultiByteToWideChar(0, CP_ACP, PChar(Value), Length(Value), PW, Len * 2);
PByte := Pw;
i := 0;
while i < Len do
begin
LoByte := PByte^;
inc(PByte);
HiByte := PByte^;
inc(PByte);
result := result + '/' + Dec2Oct(HiByte) + '/' + Dec2Oct(LoByte);
inc(i);
end;
FreeMem(PW);
end;
function TfrxPDFToolkit.Dec2Oct(i: Longint): string;
var
m: Longint;
Begin
Result := '';
while i > 0 Do
begin
m := i mod 8;
Result := Char(m + Ord('0')) + Result;
i := i div 8;
end;
Result := StringOfChar('0', 3 - Length(Result)) + Result;
end;
function TfrxPDFToolkit.StrToOct(const Value: String): String;
var
i: Integer;
begin
for i := 1 to Length(Value) do
Result := Result + '/' + Dec2Oct(Ord(Value));
end;
function TfrxPDFToolkit.Str2RTL(const Str: String): String;
var
b, i, l: Integer;
s: String;
t, f: Boolean;
begin
Result := ReverseString(Str);
l := Length(Result);
i := 1;
b := 1;
f := False;
while i <= l do
begin
t := not ((Ord(Result) > 32) and (Ord(Result) < 122));
if (t and f) then
begin
s := Copy(Result, b, i - b);
Delete(Result, b, i - b);
s := ReverseString(s);
Insert(s, Result, b);
f := False;
end;
if not (t or f) then
begin
b := i;
f := True;
end;
i := i + 1;
end;
end;
{ TfrxPDFOutlineNode }
constructor TfrxPDFOutlineNode.Create;
begin
Title := '';
Dest := -1;
Number := 0;
Count := 0;
CountTree :=0;
Parent := nil;
First := nil;
Prev := nil;
Next := nil;
Last := nil;
end;
destructor TfrxPDFOutlineNode.Destroy;
begin
if Next <> nil then
Next.Free;
if First <> nil then
First.Free;
inherited;
end;
fastreport3.x系列版本導出功能問題真多,導出excel出現"Access Violation at address 002AFCBB in module "vcl70.bpl'.Read of address 00000057."的錯誤提示,導出到RTFF打開后也是亂碼,唉,弄了幾天都沒搞定.本來是使用控件,到最后是修改控件,廠商在發布產品時不知有沒有認真測試過?
用2.5做的報表,在設計器中存成fr3格式,然后在3.x的設計器中打開提示"following error(s) have occured:couldn't find class TFrReportPage",這樣的話,那麼多的報表重做豈不是累死?唉,想升級真不容易!這樣的產品連向下兼容的功能都沒有.總之一個字:"煩"