htmlun2.pas
来自「查看html文件的控件」· PAS 代码 · 共 2,486 行 · 第 1/5 页
PAS
2,486 行
begin
if IsTransparentPNG(Stream, Color) then {check for transparent PNG}
Transparent := TPng;
PI := TPngImage.Create;
try
PI.LoadFromStream(Stream);
Result.Assign(PI);
if Result.Handle <> 0 then; {force proper initiation win98/95}
finally
PI.Free;
end;
end
{$else}
else if IT = Png then
Result := Nil
{$endif}
else
begin
Result.LoadFromStream(Stream); {Bitmap}
end;
if Transparent = LLCorner then
AMask := GetImageMask(Result, False, 0)
{$ifdef NoOldPng}
;
{$else}
else if Transparent = TPng then
begin
AMask := GetImageMask(Result, True, Color);
{Replace the background color with black. This is needed if the Png is a
background image.}
Tmp := Result;
Result := TBitmap.Create;
Result.Width := Tmp.Width;
Result.Height := Tmp.Height;
Result.Palette := CopyPalette(ThePalette);
with Result do
begin
Canvas.Brush.Color := Color;
PatBlt(Canvas.Handle, 0, 0, Width, Height, PatCopy);
SetBkColor(Canvas.Handle, clWhite);
SetTextColor(Canvas.Handle, clBlack);
BitBlt(Canvas.Handle, 0, 0, Width, Height, AMask.Canvas.Handle, 0, 0, SrcAnd);
BitBlt(Canvas.Handle, 0, 0, Width, Height, Tmp.Canvas.Handle, 0, 0, SrcInvert);
end;
Tmp.Free;
end;
{$endif}
Result := ConvertImage(Result);
except
Result.Free;
Result := Nil;
end;
end;
var
Unique: integer = 183902;
{----------------GetImageAndMaskFromStream}
function GetImageAndMaskFromStream(Stream: TMemoryStream;
var Transparent: Transparency; var AMask: TBitmap): TgpObject;
var
Filename: string;
Path: array[0..Max_Path] of char;
F: File;
I: integer;
begin
Result := Nil;
AMask := Nil;
if not Assigned(Stream) or (Stream.Memory = Nil) or (Stream.Size < 20) then
Exit;
Stream.Position := 0;
if GDIPlusActive and (KindOfImage(Stream.Memory) = png) then
begin
try
GetTempPath(Max_Path, @Path);
SetLength(Filename, Max_Path+1);
GetTempFilename(@Path, 'png', Unique, PChar(Filename));
Inc(Unique);
I := Pos(#0, Filename);
SetLength(Filename, I-1);
AssignFile(F, Filename);
ReWrite(F, 1);
BlockWrite(F, Stream.Memory^, Stream.Size);
CloseFile(F);
Result := TgpImage.Create(Filename, True); {True because it's a temporary file}
Transparent := NotTransp;
except
end;
Exit;
end;
Result := GetBitmapAndMaskFromStream(Stream, Transparent, AMask);
{$ifndef NoMetafile}
if not Assigned(Result) then
begin
Result := ThtMetafile.Create;
try
AMask := Nil;
Transparent := NotTransp;
ThtMetaFile(Result).LoadFromStream(Stream);
except
FreeAndNil(Result);
end;
end;
{$endif}
end;
function GetImageMask(Image: TBitmap; ColorValid: boolean; AColor: TColor): TBitmap;
begin
try
if ColorValid then
Image.TransparentColor := AColor; {color has already been selected}
{else the transparent color is the lower left pixel of the bitmap}
Image.Transparent := True;
Result := TBitmap.Create;
try
Result.Handle := Image.ReleaseMaskHandle;
Image.Transparent := False;
except
FreeAndNil(Result);
end;
except
Result := Nil;
end;
end;
{----------------FinishTransparentBitmap }
procedure FinishTransparentBitmap (ahdc: HDC;
InImage, Mask: TBitmap; xStart, yStart, W, H: integer);
var
bmAndBack,
bmSave,
bmBackOld,
bmObjectOld : HBitmap;
hdcInvMask,
hdcMask,
hdcImage: HDC;
DestSize, SrcSize : TPoint;
OldBack, OldFore: TColor;
BM: Windows.TBitmap;
Image: TBitmap;
begin
Image := TBitmap.Create; {protect original image}
try
Image.Assign(InImage);
hdcImage := CreateCompatibleDC (ahdc);
SelectObject (hdcImage, Image.Handle); { select the bitmap }
{ convert bitmap dimensions from device to logical points}
SrcSize.x := Image.Width;
SrcSize.y := Image.Height;
DPtoLP(hdcImage, SrcSize, 1);
DestSize.x := W;
DestSize.y := H;
DPtoLP (hdcImage, DestSize, 1);
{ create a bitmap for each DC}
{ monochrome DC}
bmAndBack := CreateBitmap (SrcSize.x, SrcSize.y, 1, 1, nil);
bmSave := CreateCompatibleBitmap (ahdc, DestSize.x, DestSize.y);
GetObject(bmSave, SizeOf(BM), @BM);
if (BM.bmBitsPixel > 1) or (BM.bmPlanes > 1) then
begin
{ create some DCs to hold temporary data}
hdcInvMask := CreateCompatibleDC(ahdc);
hdcMask := CreateCompatibleDC(ahdc);
{ each DC must select a bitmap object to store pixel data}
bmBackOld := SelectObject (hdcInvMask, bmAndBack);
{ set proper mapping mode}
SetMapMode (hdcImage, GetMapMode (ahdc));
bmObjectOld := SelectObject(hdcMask, Mask.Handle);
{ create the inverse of the object mask}
BitBlt (hdcInvMask, 0, 0, SrcSize.x, SrcSize.y, hdcMask, 0, 0, NOTSRCCOPY);
{set the background color of the source DC to the color contained in the
parts of the bitmap that should be transparent, the foreground to the parts that
will show}
OldBack := SetBkColor(ahDC, clWhite);
OldFore := SetTextColor(ahDC, clBlack);
{ Punch out a black hole in the background where the image will go}
SetStretchBltMode(ahDC, WhiteOnBlack);
StretchBlt (ahDC, XStart, YStart, DestSize.x, DestSize.y, hdcMask, 0, 0, SrcSize.x, SrcSize.y, SRCAND);
{ mask out the transparent colored pixels on the bitmap}
BitBlt (hdcImage, 0, 0, SrcSize.x, SrcSize.y, hdcInvMask, 0, 0, SRCAND);
{ XOR the bitmap with the background on the destination DC}
SetStretchBltMode(ahDC, ColorOnColor);
StretchBlt(ahDC, XStart, YStart, W, H, hdcImage, 0, 0, Image.Width, Image.Height, SRCPAINT);
SetBkColor(ahDC, OldBack);
SetTextColor(ahDC, OldFore);
{ delete the memory bitmaps}
DeleteObject (SelectObject (hdcInvMask, bmBackOld));
SelectObject (hdcMask, bmObjectOld);
{ delete the memory DCs}
DeleteDC (hdcInvMask);
DeleteDC (hdcMask);
end
else
begin
DeleteObject(bmAndBack);
end;
DeleteObject(bmSave);
DeleteDC (hdcImage);
finally
Image.Free;
end;
end;
{----------------TDib.CreateDIB}
constructor TDib.CreateDIB(DC: HDC; Bitmap: TBitmap);
{given a TBitmap, construct a device independent bitmap}
var
ImgSize: DWord;
begin
InitializeBitmapInfoHeader(Bitmap.Handle);
ImgSize := Info^.biSizeImage;
Allocate(ImgSize);
try
GetDIBX(DC, Bitmap.Handle, Bitmap.Palette);
except
DeAllocate;
Raise;
end;
end;
destructor TDib.Destroy;
begin
DeAllocate;
inherited Destroy;
end;
procedure TDib.Allocate(Size: integer);
begin
ImageSize := Size;
if Size < $FF00 then
GetMem(Image, Size)
else
begin
FHandle := GlobalAlloc(HeapAllocFlags, Size);
if FHandle = 0 then
ABort;
Image := GlobalLock(FHandle);
end;
end;
procedure TDib.DeAllocate;
begin
if ImageSize > 0 then
begin
if ImageSize < $FF00 then
Freemem(Image, ImageSize)
else
begin
GlobalUnlock(FHandle);
GlobalFree(FHandle);
end;
ImageSize := 0;
end;
if InfoSize > 0 then
begin
FreeMem(Info, InfoSize);
InfoSize := 0;
end;
end;
procedure TDib.InitializeBitmapInfoHeader(Bitmap: HBITMAP);
var
BM: Windows.TBitmap;
BitCount: integer;
function WidthBytes(I: integer): integer;
begin
Result := ((I + 31) div 32) * 4;
end;
begin
GetObject(Bitmap, SizeOf(BM), @BM);
BitCount := BM.bmBitsPixel * BM.bmPlanes;
if BitCount > 8 then
InfoSize := SizeOf(TBitmapInfoHeader)
else
InfoSize := SizeOf(TBitmapInfoHeader) + SizeOf(TRGBQuad) * (1 shl BitCount);
GetMem(Info, InfoSize);
with Info^ do
begin
biSize := SizeOf(TBitmapInfoHeader);
biWidth := BM.bmWidth;
biHeight := BM.bmHeight;
biBitCount := BM.bmBitsPixel * BM.bmPlanes;
biPlanes := 1;
biXPelsPerMeter := 0;
biYPelsPerMeter := 0;
biClrUsed := 0;
biClrImportant := 0;
biCompression := BI_RGB;
if biBitCount in [16, 32] then
biBitCount := 24;
biSizeImage := WidthBytes(biWidth * biBitCount) * biHeight;
end;
end;
procedure TDib.GetDIBX(DC: HDC; Bitmap: HBITMAP; Palette: HPALETTE);
var
OldPal: HPALETTE;
Rslt: integer;
bmInfo: PBitmapInfo;
begin
OldPal := 0;
if Palette <> 0 then
begin
OldPal := SelectPalette(DC, Palette, False);
RealizePalette(DC);
end;
bmInfo := PBitmapInfo(Info);
Rslt := GetDIBits(DC, Bitmap, 0, Info^.biHeight, Image, bmInfo^, DIB_RGB_COLORS);
if OldPal <> 0 then
SelectPalette(DC, OldPal, False);
if Rslt = 0 then
begin
OutofMemoryError;
end;
end;
procedure TDib.DrawDIB(DC: HDC; X: Integer; Y: integer; W, H: integer;
ROP: DWord);
var
bmInfo: PBitmapInfo;
begin
bmInfo := PBitmapInfo(Info);
with Info^ do
StretchDIBits(DC, X, Y, W, H, 0, 0, biWidth, biHeight, Image,
bmInfo^, DIB_RGB_COLORS, ROP);
end;
function TDib.CreateDIBmp: hBitmap;
var
bmInfo: PBitmapInfo;
DC: HDC;
OldPal: HPalette;
begin
bmInfo := PBitmapInfo(Info);
DC := GetDC(0);
OldPal := SelectPalette(DC, ThePalette, False);
RealizePalette(DC);
try
Result := CreateDIBitmap(DC, bmInfo^.bmiHeader, CBM_INIT, Image,
bmInfo^, DIB_RGB_COLORS);
finally
SelectPalette(DC, OldPal, False);
ReleaseDC(0, DC);
end;
end;
{----------------IndentManagerBasic.Create}
constructor IndentManagerBasic.Create;
begin
inherited Create;
R := TFreeList.Create;
L := TFreeList.Create;
end;
destructor IndentManagerBasic.Destroy;
begin
R.Free;
L.Free;
inherited Destroy;
end;
procedure IndentManagerBasic.Clear;
begin
R.Clear;
L.Clear;
CurrentID := Nil;
end;
{----------------IndentManagerBasic.Reset}
procedure IndentManagerBasic.Reset(Lf, Rt: integer);
begin
LfEdge := Lf;
RtEdge := Rt;
CurrentID := Nil;
end;
procedure IndentManagerBasic.UpdateTable(Y: integer; IW: integer; IH: integer;
Justify: JustifyType);
{Given a floating table, update the edge information. }
var
IR: IndentRec;
begin
IR := IndentRec.Create;
if (Justify = Left) then
begin
with IR do
begin
X := -LfEdge + IW;
YT := Y;
YB := Y + IH;
L.Add(IR);
end;
end
else if (Justify = Right) then
begin
with IR do
begin
X := RightSide(Y) - IW;
YT := Y;
YB := Y + IH;
R.Add(IR);
end;
end;
end;
const
BigY = 9999999;
function IndentManagerBasic.LeftIndent(Y: integer): integer;
var
I: integer;
begin
Result := -99999;
for I := 0 to L.Count-1 do
with IndentRec(L.Items[I]) do
begin
if (Y >= YT) and (Y < YB) and (Result < X) then
if not Assigned(ID) or (ID = CurrentID) then
Result := X;
end;
if Result = -99999 then
Result := 0;
Inc(Result, LfEdge);
end;
function IndentManagerBasic.RightSide(Y: integer): integer;
{returns the current right side dimension as measured from the left, a positive
number}
var
I: integer;
IR: IndentRec;
begin
Result := 99999;
for I := 0 to R.Count-1 do
begin
IR := IndentRec(R.Items[I]);
with IR do
if (Y >= YT) and (Y < YB) and (Result > X) then
if not Assigned(ID) or (ID = CurrentID) then
Result := X;
end;
if Result = 99999 then
Result := RtEdge
else Inc(Result, LfEdge);
end;
function IndentManagerBasic.ImageBottom: integer;
{finds the bottom of the last floating image}
var
I: integer;
begin
Result := 0;
for I := 0 to L.Count-1 do
with IndentRec(L.Items[I]) do
if not Assigned(ID) and (YB > Result) then
Result := YB;
for I := 0 to R.Count-1 do
with IndentRec(R.Items[I]) do
if not Assigned(ID) and (YB > Result) then
Result := YB;
end;
procedure IndentManagerBasic.GetClearY(var CL, CR: integer);
{returns the left and right Y values which will clear image margins}
var
I: integer;
begin
CL := -1;
for I := 0 to L.Count-1 do
with IndentRec(L.Items[I]) do
if not Assigned(ID
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?