From 364eceef0740edfcebf7b617ba8cd26d8fc8f483 Mon Sep 17 00:00:00 2001 From: zueuk Date: Wed, 6 Sep 2006 12:44:29 +0000 Subject: [PATCH] too many chages... --- 2.10/Source/Adjust.dfm | 35 +- 2.10/Source/Adjust.pas | 158 +++++---- 2.10/Source/ControlPoint.pas | 99 ++++-- 2.10/Source/Editor.dfm | 10 +- 2.10/Source/Editor.pas | 117 +++---- 2.10/Source/FormRender.dfm | 8 +- 2.10/Source/FormRender.pas | 142 ++++----- 2.10/Source/ImageMaker.pas | 25 +- 2.10/Source/Main.pas | 599 ++++++++++++++++++++++++++--------- 2.10/Source/Preview.pas | 1 + 10 files changed, 765 insertions(+), 429 deletions(-) diff --git a/2.10/Source/Adjust.dfm b/2.10/Source/Adjust.dfm index b68cc59..d602fa9 100644 --- a/2.10/Source/Adjust.dfm +++ b/2.10/Source/Adjust.dfm @@ -178,9 +178,11 @@ object AdjustForm: TAdjustForm Height = 129 ActivePage = TabSheet1 Align = alBottom + Images = MainForm.Buttons TabOrder = 1 object TabSheet1: TTabSheet Caption = 'Camera' + ImageIndex = 18 object scrollZoom: TScrollBar Left = 72 Top = 7 @@ -263,6 +265,7 @@ object AdjustForm: TAdjustForm Height = 15 LargeChange = 1500 Max = 36000 + Min = -36000 PageSize = 0 SmallChange = 100 TabOrder = 6 @@ -351,7 +354,7 @@ object AdjustForm: TAdjustForm end object TabSheet2: TTabSheet Caption = 'Rendering' - ImageIndex = 1 + ImageIndex = 35 object lblContrast: TLabel Left = 4 Top = 80 @@ -532,7 +535,7 @@ object AdjustForm: TAdjustForm end object TabSheet3: TTabSheet Caption = 'Gradient' - ImageIndex = 2 + ImageIndex = 11 object lblVal: TLabel Left = 358 Top = 55 @@ -866,7 +869,7 @@ object AdjustForm: TAdjustForm end object TabSheet4: TTabSheet Caption = 'Image Size' - ImageIndex = 3 + ImageIndex = 51 object Bevel2: TBevel Left = 4 Top = 4 @@ -895,6 +898,13 @@ object AdjustForm: TAdjustForm Height = 13 Caption = 'Height' end + object Bevel3: TBevel + Left = 302 + Top = 4 + Width = 73 + Height = 93 + Shape = bsFrame + end object btnPreset1: TButton Left = 156 Top = 12 @@ -950,9 +960,9 @@ object AdjustForm: TAdjustForm OnClick = btnSet3Click end object btnApplySize: TBitBtn - Left = 302 - Top = 72 - Width = 75 + Left = 308 + Top = 64 + Width = 61 Height = 25 Caption = 'Apply' TabOrder = 6 @@ -1004,6 +1014,18 @@ object AdjustForm: TAdjustForm '960' '1024') end + object chkResizeMain: TCheckBox + Left = 308 + Top = 10 + Width = 61 + Height = 50 + Alignment = taLeftJustify + Caption = 'Resize Main Window' + Checked = True + State = cbChecked + TabOrder = 10 + WordWrap = True + end end end object QualityPopup: TPopupMenu @@ -1031,6 +1053,7 @@ object AdjustForm: TAdjustForm end object mnuInstantPreview: TMenuItem Caption = 'Instant Preview' + Checked = True OnClick = mnuInstantPreviewClick end end diff --git a/2.10/Source/Adjust.pas b/2.10/Source/Adjust.pas index 26a8bea..27f3dba 100644 --- a/2.10/Source/Adjust.pas +++ b/2.10/Source/Adjust.pas @@ -133,6 +133,8 @@ type pnlGamma: TPanel; pnlBrightness: TPanel; pnlVibrancy: TPanel; + chkResizeMain: TCheckBox; + Bevel3: TBevel; procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormDestroy(Sender: TObject); @@ -356,36 +358,36 @@ begin // zoom := MainForm.zoom; // cp.zoom := zoom; - Resetting := True; // So the preview doesn't get drawn with these changes.. - scrollGamma.Position := trunc(cp.Gamma * 100); - scrollBrightness.Position := trunc(cp.Brightness * 100); - scrollVibrancy.Position := trunc(cp.vibrancy * 100); - scrollZoom.Position := trunc(cp.zoom * 1000); + Resetting := True; // So the preview doesn't get drawn with these changes.. + scrollGamma.Position := trunc(cp.Gamma * 100); + scrollBrightness.Position := trunc(cp.Brightness * 100); + scrollVibrancy.Position := trunc(cp.vibrancy * 100); + scrollZoom.Position := trunc(cp.zoom * 1000); // ScrollAngle.Position := Trunc(cp.FAngle * 18000.0 / PI) mod scrollAngle.Max; - scrollAngle.Position := Trunc((cp.FAngle + pi)* 18000.0 / PI) mod 36000; + scrollAngle.Position := Trunc(cp.FAngle * 18000.0 / PI) mod 36000; - if (abs(cp.Center[0]) < 1000) and (abs(cp.Center[1]) < 1000) then begin - scrollCenterX.Position := trunc(cp.Center[0] * 1000); - scrollCenterY.Position := trunc(cp.Center[1] * 1000); - end else begin - scrollCenterX.Position := 0; - scrollCenterY.Position := 0; - end; + if (abs(cp.Center[0]) < 1000) and (abs(cp.Center[1]) < 1000) then begin + scrollCenterX.Position := trunc(cp.Center[0] * 1000); + scrollCenterY.Position := trunc(cp.Center[1] * 1000); + end else begin + scrollCenterX.Position := 0; + scrollCenterY.Position := 0; + end; - ColorPanel.color := cp.background[2] shl 16 + cp.background[1] shl 8 + cp.background[0]; - //cbColor.text := IntToHex(integer(ColorPanel.Color), 6); + ColorPanel.color := cp.background[2] shl 16 + cp.background[1] shl 8 + cp.background[0]; + //cbColor.text := IntToHex(integer(ColorPanel.Color), 6); - GetMainWindowSize; + GetMainWindowSize; - // gradient - if cp.cmapindex >= 0 then - cmbPalette.ItemIndex := cp.cmapindex; - ScrollBar.Position := 0; - Palette := cp.cmap; - BackupPal := cp.cmap; + // gradient + if cp.cmapindex >= 0 then + cmbPalette.ItemIndex := cp.cmapindex; + ScrollBar.Position := 0; + Palette := cp.cmap; + BackupPal := cp.cmap; - Resetting := False; -editPPU.Text := Format('%.6g', [cp.pixels_per_unit]); + Resetting := False; + editPPU.Text := Format('%.6g', [100*cp.pixels_per_unit/PreviewImage.Width]); end; //*** DrawPreview; end; @@ -394,7 +396,7 @@ procedure TAdjustForm.UpdateFlame; begin MainForm.StopThread; MainForm.UpdateUndo; - MainCp.Copy(cp); + MainCp.Copy(cp, true); // MainCp.cmap := cmap; // MainForm.zoom := zoom; // MainForm.Center[0] := Center[0]; @@ -488,6 +490,7 @@ begin Registry.WriteInteger('Top', AdjustForm.Top); Registry.WriteInteger('Left', AdjustForm.Left); Registry.WriteBool('InstantPreview', mnuInstantPreview.Checked); + Registry.WriteBool('ResizeMain', chkResizeMain.Checked); end; finally Registry.Free; @@ -521,6 +524,8 @@ begin AdjustForm.Top := Registry.ReadInteger('Top'); if Registry.ValueExists('InstantPreview') then mnuInstantPreview.Checked := Registry.ReadBool('InstantPreview'); + if Registry.ValueExists('ResizeMain') then + chkResizeMain.Checked := Registry.ReadBool('ResizeMain'); Registry.CloseKey; end; @@ -827,7 +832,7 @@ begin ScrollVibrancy.Position := v; UpdateFlame; except on EConvertError do - txtVibrancy.Text := FloatToStr(cp.Vibrancy); + txtVibrancy.Text := FloatToStr(cp.Vibrancy); end; end; @@ -871,6 +876,7 @@ procedure TAdjustForm.scrollVibrancyChange(Sender: TObject); begin cp.Vibrancy := ScrollVibrancy.Position / 100; txtVibrancy.text := FloatToStr(cp.Vibrancy); + txtVibrancy.Refresh; DrawPreview; end; @@ -878,6 +884,7 @@ procedure TAdjustForm.scrollGammaChange(Sender: TObject); begin cp.Gamma := scrollGamma.Position / 100; txtGamma.text := FloatToStr(cp.Gamma); + txtGamma.Refresh; DrawPreview; end; @@ -885,6 +892,7 @@ procedure TAdjustForm.scrollBrightnessChange(Sender: TObject); begin cp.Brightness := ScrollBrightness.Position / 100; txtBrightness.text := FloatToStr(cp.Brightness); + txtBrightness.Refresh; DrawPreview; end; @@ -892,6 +900,7 @@ procedure TAdjustForm.scrollZoomChange(Sender: TObject); begin cp.zoom := scrollZoom.Position / 1000; txtZoom.text := FloatToStr(cp.zoom); + txtZoom.Refresh; DrawPreview; end; @@ -899,13 +908,15 @@ procedure TAdjustForm.scrollCenterXChange(Sender: TObject); begin cp.center[0] := scrollCenterX.Position / 1000; txtCenterX.text := FloatToStr(cp.center[0]); + txtCenterX.Refresh; DrawPreview; end; procedure TAdjustForm.scrollCenterYChange(Sender: TObject); begin cp.center[1] := scrollCenterY.Position / 1000; - txtCentery.text := FloatToStr(cp.center[1]); + txtCenterY.text := FloatToStr(cp.center[1]); + txtCenterY.Refresh; DrawPreview; end; @@ -935,8 +946,9 @@ end; procedure TAdjustForm.scrollAngleChange(Sender: TObject); begin - cp.FAngle := (scrollAngle.Position - 18000) * PI / 18000.0; + cp.FAngle := scrollAngle.Position * PI / 18000.0; txtAngle.text := FloatToStr(cp.FAngle * 180 / PI); + txtAngle.Refresh; DrawPreview; end; @@ -959,7 +971,7 @@ begin begin key := #0; try - v := Trunc(StrToFloat(txtAngle.Text) * 100) mod scrollAngle.Max - 18000; + v := Trunc(StrToFloat(txtAngle.Text) * 100) mod scrollAngle.Max; //if v > scrollAngle.Max then v := v - scrollAngle.Max*2 if v < scrollAngle.Min then v := v + scrollAngle.Max; ScrollAngle.Position := v; @@ -976,9 +988,9 @@ var begin if (txtAngle.Text <> EditBoxValue) then try - v := Trunc(StrToFloat(txtAngle.Text) * 100) mod (scrollAngle.Max*2); - if v > scrollAngle.Max then v := v - scrollAngle.Max*2 - else if v < scrollAngle.Min then v := v + scrollAngle.Max*2; + v := Trunc(StrToFloat(txtAngle.Text) * 100) mod scrollAngle.Max; +// if v > scrollAngle.Max then v := v - scrollAngle.Max*2 +// else if v < scrollAngle.Min then v := v + scrollAngle.Max*2; ScrollAngle.Position := v; UpdateFlame; except on EConvertError do @@ -1687,8 +1699,10 @@ begin txtWidth.Text := IntToStr(ImageWidth); txtHeight.Text := IntToStr(ImageHeight); - MainForm.Left:=Preset[n].Left; - MainForm.Top:=Preset[n].Top; + if chkResizeMain.Checked then begin + MainForm.Left:=Preset[n].Left; + MainForm.Top:=Preset[n].Top; + end; SetMainWindowSize; end; @@ -1739,28 +1753,36 @@ end; procedure TAdjustForm.SetMainWindowSize; var - xtot, ytot: integer; + l, t, w, h: integer; begin - xtot := ImageWidth + (MainForm.Width - MainForm.Image.Width); - ytot := ImageHeight + (MainForm.Height - MainForm.Image.Height); - if xtot > Screen.Width then - begin - MainForm.Left := 0; - xtot := Screen.width; - end; - if ytot > Screen.height then - begin - MainForm.Top := 0; - ytot := Screen.height; - end; - MainForm.Width := xtot; - MainForm.Height := ytot; + MainCp.AdjustScale(ImageWidth, ImageHeight); + MainForm.ResizeImage; //? + + if chkResizeMain.Checked then begin + l := MainForm.Left; + t := MainForm.Top; + w := ImageWidth + MainForm.Width - (MainForm.BackPanel.Width - 2); + h := ImageHeight + MainForm.Height - (MainForm.BackPanel.Height - 2); + if w > Screen.Width then + begin + l := 0; + w := Screen.width; + end; + if h > Screen.height then + begin + t := 0; + h := Screen.height; + end; + + MainForm.SetBounds(l, t, w, h); + end + else MainForm.RedrawTimer.Enabled := true; end; procedure TAdjustForm.GetMainWindowSize; begin - ImageWidth := MainForm.Image.Width; - ImageHeight := MainForm.Image.Height; + ImageWidth := MainCP.Width; //MainForm.Image.Width; + ImageHeight := MainCP.Height; //MainForm.Image.Height; txtWidth.text := IntToStr(ImageWidth); txtHeight.text := IntToStr(ImageHeight); end; @@ -1872,7 +1894,7 @@ begin exit; end; MainForm.UpdateUndo; - cp.pixels_per_unit := v; + cp.pixels_per_unit := v/100*PreviewImage.Width; UpdateFlame; end; @@ -1884,7 +1906,7 @@ begin if Button <> mbLeft then exit; if (Sender = pnlMasterScale) then - pnlDragValue := cp.pixels_per_unit / 10 + pnlDragValue := cp.pixels_per_unit / PreviewImage.Width else if (Sender = pnlZoom) then pnlDragValue := cp.zoom else if (Sender = pnlXpos) then @@ -1915,7 +1937,7 @@ end; procedure TAdjustForm.DragPanelMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); var - v: double; + sc, v: double; begin if pnlMM then // hack: to skip MouseMove event begin @@ -1926,22 +1948,22 @@ begin begin Inc(pnlDragPos, x - pnlDragOld); - if GetKeyState(VK_MENU) < 0 then v := 100000 - else if GetKeyState(VK_CONTROL) < 0 then v := 10000 - else if GetKeyState(VK_SHIFT) < 0 then v := 100 - else v := 1000; + if GetKeyState(VK_MENU) < 0 then sc := 100000 + else if GetKeyState(VK_CONTROL) < 0 then sc := 10000 + else if GetKeyState(VK_SHIFT) < 0 then sc := 100 + else sc := 1000; - v := Round6(pnlDragValue + pnlDragPos / v); + v := Round6(pnlDragValue + pnlDragPos / sc); SetCursorPos(MousePos.x, MousePos.y); // hmmm pnlMM:=true; if (Sender = pnlMasterScale) then begin - v := v * 10; - if v <= 0.1 then v := 0.1; - cp.pixels_per_unit := v; - editPPU.Text := FloatToStr(v); + v := Round6(pnlDragValue * power(2, pnlDragPos / sc / 2)); + if v <= 0.0001 then v := 0.0001; + cp.pixels_per_unit := v*PreviewImage.Width; + editPPU.Text := FloatToStr(v*100); end else if (Sender = pnlZoom) then begin @@ -1957,7 +1979,7 @@ begin end else if (Sender = pnlAngle) then begin - scrollAngle.Position := Trunc((v + pi)* 18000.0 / PI) mod 36000; + scrollAngle.Position := Trunc(v * 18000.0 / PI) mod 36000; end else if (Sender = pnlGamma) then begin @@ -2005,9 +2027,9 @@ begin if (Sender = pnlMasterScale) then begin pValue := @cp.pixels_per_unit; - if pValue^ = 32 then exit; - pValue^ := 32; - editPPU.Text := FloatToStr(pValue^); + if pValue^ = PreviewImage.Width/4 then exit; + pValue^ := PreviewImage.Width/4; + editPPU.Text := FloatToStr(100*pValue^/PreviewImage.Width); end else if (Sender = pnlZoom) then begin @@ -2023,7 +2045,7 @@ begin end else if (Sender = pnlAngle) then begin - scrollAngle.Position := 18000; + scrollAngle.Position := 0; end else if (Sender = pnlGamma) then begin diff --git a/2.10/Source/ControlPoint.pas b/2.10/Source/ControlPoint.pas index 16726bc..8d2a7bd 100644 --- a/2.10/Source/ControlPoint.pas +++ b/2.10/Source/ControlPoint.pas @@ -1,7 +1,7 @@ { Flame screensaver Copyright (C) 2002 Ronald Hordijk Apophysis Copyright (C) 2001-2004 Mark Townsend - Apophysis Copyright (C) 2005-2006 Ronald Hordijk, Piotr Borys, Peter Sdobnov + Apophysis Copyright (C) 2005-2006 Ronald Hordijk, Piotr Borys, Peter Sdobnov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -34,8 +34,6 @@ const BRIGHT_ADJUST = 2.3; FUSE = 15; -// ---- MyTypes ---- - type TCoefsArray= array[0..2, 0..1] of double; pCoefsArray= ^TCoefsArray; @@ -67,8 +65,6 @@ type TPreviewPixArray = array[0..159, 0..119, 0..3] of integer; TFileType = (ftIfs, ftFla, ftXML); -// ----- - type //? PLongintArray = ^TLongintArray; TLongintArray = array[0..8192] of Longint; @@ -118,7 +114,7 @@ type (* in order to motion blur more accurately we compute the logs of the sample density many times and average the results. we interplate only this many times. *) - actual_density: extended; // for incomplete renders + actual_density: extended; // for incomplete renders nbatches: integer; // this much color resolution. but making it too high induces clipping white_level: integer; cmap_inter: integer; // if this is true, then color map interpolates one entry @@ -164,15 +160,19 @@ type // procedure Testiterate(NrPoints: integer; var Points: TPointsArray); function Clone: TControlPoint; - procedure Copy(cp1: TControlPoint); + procedure Copy(cp1: TControlPoint; KeepSizes: boolean = false); - function HasNewVariants: boolean; +// function HasNewVariants: boolean; function HasFinalXForm: boolean; // CP-specific functions moved from unit Main function NumXForms: integer; function TrianglesFromCP(var Triangles: TTriangles): integer; procedure GetFromTriangles(const Triangles: TTriangles; const t: integer); + + procedure GetPostTriangle(var Triangles: TTriangles; const n: integer); + procedure SetPostTriangle(const Triangles: TTriangles; const n: integer); + procedure EqualizeWeights; procedure NormalizeWeights; procedure RandomizeWeights; @@ -913,6 +913,7 @@ var deltay, miny, maxy: double; cntminy, cntmaxy: integer; LimitOutSidePoints: integer; + px, py, sina, cosa: double; begin {$IFDEF TESTVARIANT} center[0] := 0; @@ -929,6 +930,9 @@ begin 1: iterateXYC(SUB_BATCH_SIZE, points); end; } + cosa := cos(FAngle); + sina := sin(FAngle); + Prepare; IterateXY(SUB_BATCH_SIZE, points); @@ -960,6 +964,8 @@ begin cntminy := 0; cntmaxy := 0; for i := 0 to SUB_BATCH_SIZE - 1 do begin + px := points[i].x * cosa + points[i].y * sina; + py := points[i].y * cosa - points[i].x * sina; if (Points[i].x < minx) then Inc(cntminx); if (Points[i].x > maxx) then Inc(cntmaxx); if (Points[i].y < miny) then Inc(cntminy); @@ -1490,11 +1496,15 @@ begin sl.Free; end; -procedure TControlPoint.Copy(cp1: TControlPoint); +procedure TControlPoint.Copy(cp1: TControlPoint; KeepSizes: boolean = false); var i: integer; sl: TStringList; + w, h: integer; begin + w := Width; + h := Height; + Clear; sl := TStringList.Create; @@ -1503,11 +1513,17 @@ begin ParseStringlist(sl); Fangle := cp1.FAngle; + center[0]:= cp1.center[0]; + center[1]:= cp1.center[1]; + pixels_per_unit := cp1.pixels_per_unit; cmap := cp1.cmap; name := cp1.name; nick := cp1.nick; url := cp1.url; + if KeepSizes then + AdjustScale(w, h); + for i := 0 to NXFORMS do // was: NXFORMS-1 xform[i].assign(cp1.xform[i]); finalXformEnabled := cp1.finalXformEnabled; @@ -1649,6 +1665,7 @@ begin end; end; +(* /////////////////////////////////////////////////////////////////////////////// function TControlPoint.HasNewVariants: boolean; var @@ -1668,47 +1685,40 @@ begin end; } end; +*) /////////////////////////////////////////////////////////////////////////////// procedure TControlPoint.ZoomtoRect(R: TRect); var - scale: double; - ppux, ppuy: double; + scale, ppu: double; dx,dy: double; begin scale := power(2, zoom); - ppux := pixels_per_unit * scale; - ppuy := pixels_per_unit * scale; + ppu := pixels_per_unit * scale; - dx := ((r.Left + r.Right)/2 - Width/2)/ppux ; - dy := ((r.Top + r.Bottom)/2 - Height/2)/ppuy; + dx := ((r.Left + r.Right)/2 - Width/2) / ppu; + dy := ((r.Top + r.Bottom)/2 - Height/2) / ppu; center[0] := center[0] + cos(FAngle) * dx - sin(FAngle) * dy; - center[1] := center[1] + sin(FAngle) * dx + cos(FAngle) * dy ; + center[1] := center[1] + sin(FAngle) * dx + cos(FAngle) * dy; - Scale := Scale * Min( Width/(abs(r.Right - r.Left) + 1), Height/(abs(r.Bottom - r.Top) + 1)) ; - Zoom := Log2(Scale); + zoom := Log2(scale * ( Width/(abs(r.Right - r.Left) + 1))); end; /////////////////////////////////////////////////////////////////////////////// procedure TControlPoint.ZoomOuttoRect(R: TRect); var - scale: double; - ppux, ppuy: double; - dx,dy: double; + ppu: double; + dx, dy: double; begin - scale := power(2, zoom); - ppux := pixels_per_unit * scale; - ppuy := pixels_per_unit * scale; + zoom := Log2(power(2, zoom) / ( Width/(abs(r.Right - r.Left) + 1))); + ppu := pixels_per_unit * power(2, zoom); - dx := ((r.Left + r.Right)/2 - Width/2)/ppux ; - dy := ((r.Top + r.Bottom)/2 - Height/2)/ppuy; + dx := ((r.Left + r.Right)/2 - Width/2) / ppu; + dy := ((r.Top + r.Bottom)/2 - Height/2) / ppu; - center[0] := center[0] + cos(FAngle) * dx - sin(FAngle) * dy; - center[1] := center[1] + sin(FAngle) * dx + cos(FAngle) * dy ; - - Scale := Scale / Min( Width/(abs(r.Right - r.Left) + 1), Height/(abs(r.Bottom - r.Top) + 1)) ; - Zoom := Log2(Scale); + center[0] := center[0] - cos(FAngle) * dx + sin(FAngle) * dy; + center[1] := center[1] - sin(FAngle) * dx - cos(FAngle) * dy; end; /////////////////////////////////////////////////////////////////////////////// @@ -1960,6 +1970,33 @@ begin FinalXformEnabled := EnableFinalXform; end; + +procedure TControlPoint.GetPostTriangle(var Triangles: TTriangles; const n: integer); +var + i, j: integer; +begin + for i := 0 to 2 do + with xform[n] do begin + Triangles[n].x[i] := Triangles[-1].x[i] * p[0][0] + Triangles[-1].y[i] * p[1][0] + p[2][0]; + Triangles[n].y[i] := Triangles[-1].x[i] * p[0][1] + Triangles[-1].y[i] * p[1][1] + p[2][1]; + end; + //for i := 0 to 2 do Triangles[n].y[i] := -Triangles[n].y[i]; +end; + +procedure TControlPoint.SetPostTriangle(const Triangles: TTriangles; const n: integer); +begin + solve3(Triangles[-1].x[0], -Triangles[-1].y[0], Triangles[n].x[0], + Triangles[-1].x[1], -Triangles[-1].y[1], Triangles[n].x[1], + Triangles[-1].x[2], -Triangles[-1].y[2], Triangles[n].x[2], + xform[n].p[0][0], xform[n].p[1][0], xform[n].p[2][0]); + + solve3(Triangles[-1].x[0], -Triangles[-1].y[0], -Triangles[n].y[0], + Triangles[-1].x[1], -Triangles[-1].y[1], -Triangles[n].y[1], + Triangles[-1].x[2], -Triangles[-1].y[2], -Triangles[n].y[2], + xform[n].p[0][1], xform[n].p[1][1], xform[n].p[2][1]); +end; + +//////////////////////////////////////////////////////////////////////////////// procedure TControlPoint.AdjustScale(w, h: integer); begin // if width >= height then diff --git a/2.10/Source/Editor.dfm b/2.10/Source/Editor.dfm index f842567..eeb291f 100644 --- a/2.10/Source/Editor.dfm +++ b/2.10/Source/Editor.dfm @@ -412,8 +412,9 @@ object EditForm: TEditForm Top = 1 Width = 170 Height = 130 - IncrementalDisplay = True + Center = True PopupMenu = QualityPopup + Proportional = True end end object ControlPanel: TPanel @@ -1193,7 +1194,7 @@ object EditForm: TEditForm ShowHint = True OnClick = btnResetPostXFormClick end - object btnSwapXforms: TSpeedButton + object btnPostTriangle: TSpeedButton Left = 8 Top = 260 Width = 145 @@ -1209,7 +1210,7 @@ object EditForm: TEditForm ParentFont = False ParentShowHint = False ShowHint = True - OnClick = btnSwapXformsClick + OnClick = btnPostTriangleClick end object pnlWeight: TPanel Left = 8 @@ -1695,8 +1696,7 @@ object EditForm: TEditForm Caption = '-' end object mnuResetLoc: TMenuItem - Caption = 'Reset Location' - Checked = True + Caption = 'Auto reset location' OnClick = mnuResetLocClick end end diff --git a/2.10/Source/Editor.pas b/2.10/Source/Editor.pas index 53584f5..c2f039c 100644 --- a/2.10/Source/Editor.pas +++ b/2.10/Source/Editor.pas @@ -28,12 +28,6 @@ uses ControlPoint, XForm, cmap, CustomDrawControl, Render; -const - crEditArrow = 20; - crEditMove = 21; - crEditRotate = 22; - crEditScale = 23; - type TEditForm = class(TForm) GrphPnl: TPanel; @@ -145,7 +139,7 @@ type txtPost20: TEdit; txtPost21: TEdit; btnResetPostXForm: TSpeedButton; - btnSwapXforms: TSpeedButton; + btnPostTriangle: TSpeedButton; GroupBox3: TGroupBox; editPivotY: TEdit; editPivotX: TEdit; @@ -274,9 +268,6 @@ type Shift: TShiftState; X, Y: Integer); procedure VEVarsDblClick(Sender: TObject); -// procedure vleVariablesGetPickList(Sender: TObject; const KeyName: String; Values: TStrings); -// procedure vleVariablesStringsChange(Sender: TObject); - procedure cbTransformsDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); @@ -302,7 +293,7 @@ type procedure PostCoefValidate(Sender: TObject); procedure PostCoefKeypress(Sender: TObject; var Key: Char); procedure btnResetPostXFormClick(Sender: TObject); - procedure btnSwapXformsClick(Sender: TObject); + procedure btnPostTriangleClick(Sender: TObject); procedure btnPivotModeClick(Sender: TObject); procedure PivotValidate(Sender: TObject); procedure PivotKeyPress(Sender: TObject; var Key: Char); @@ -353,7 +344,6 @@ type SelectMode, ExtendedEdit, AxisLock: boolean; showVarPreview: boolean; - // --Z-- variables moved from outside GraphZoom: double; TriangleCaught, CornerCaught, EdgeCaught: boolean; LocalAxisLocked: boolean; @@ -371,12 +361,6 @@ type pnlDragPos, pnlDragOld: integer; pnlDragValue: double; -(* - { Options } - UseFlameBackground, UseTransformColors: boolean; - BackGroundColor, ReferenceTrianglecolor: integer; - GridColor1, GridColor2, HelpersColor: integer; -*) procedure UpdateFlameX; procedure UpdateFlame(DrawMain: boolean); procedure UpdateWidgets; @@ -384,15 +368,13 @@ type function GetPivot: TSPoint; overload; function GetPivot(n: integer): TSPoint; overload; -//moved to public: function GetTriangleColor(n: integer): TColor; - // --Z-- functions moved from outside (?) procedure ShowSelectedInfo; procedure Scale(var fx, fy: double; x, y: integer); -// procedure ReadjustWeights(var cp: TControlPoint); procedure TriangleViewPaint(Sender: TObject); procedure AutoZoom; + public cp: TControlPoint; Render: TRenderer; @@ -414,7 +396,6 @@ const var EditForm: TEditForm; -// pcenterx, pcentery, pscale: double; function ColorValToColor(c: TColorMap; index: double): TColor; function FlipTriangleVertical(t: TTriangle): TTriangle; @@ -428,7 +409,6 @@ function Centroid(t: TTriangle): TSPoint; function OffsetTriangleRandom(t: TTriangle): TTriangle; function ScaleTriangleCenter(t: TTriangle; scale: double): TTriangle; function ScaleTrianglePoint(t: TTriangle; x, y, scale: double): TTriangle; -//procedure ScaleAll; implementation @@ -580,29 +560,30 @@ function ColorValToColor(c: TColorMap; index: double): TColor; var i: integer; begin - i := Trunc(Index * 255); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! >>TODO: check<< + i := Trunc(Index * 255); + assert(i >= 0); + assert(i < 256); result := c[i][2] shl 16 + c[i][1] shl 8 + c[i][0]; end; procedure TEditForm.UpdatePreview; var pw, ph: integer; - r: double; begin pw := PrevPnl.Width - 2; ph := PrevPnl.Height - 2; - if (cp.width / cp.height) > (PrevPnl.Width / PrevPnl.Height) then + if (cp.width / cp.height) > (pw / ph) then begin PreviewImage.Width := pw; - r := cp.width / PreviewImage.Width; - PreviewImage.height := round(cp.height / r); + assert(pw <> 0); + PreviewImage.Height := round(cp.height / cp.Width * pw); PreviewImage.Left := 1; PreviewImage.Top := (ph - PreviewImage.Height) div 2; end else begin PreviewImage.Height := ph; - r := cp.height / PreviewImage.height; - PreviewImage.Width := round(cp.Width / r); + assert(ph <> 0); + PreviewImage.Width := round(cp.Width / cp.Height * ph); PreviewImage.Top := 1; PreviewImage.Left := (pw - PreviewImage.Width) div 2; end; @@ -613,7 +594,6 @@ end; procedure TEditForm.UpdateDisplay(PreviewOnly: boolean = false); var i: integer; -// pw, ph: integer; begin // currently EditForm does not really know if we select another // flame in the Main Window - which is not good... @@ -651,7 +631,7 @@ begin TriangleCaught := false; ShowSelectedInfo; - if MainForm.UndoIndex = 0 then AutoZoom // auto-zoom only on 'new' flame - hmm...? + if MainForm.UndoIndex = 0 then AutoZoom // auto-zoom only on 'new' flame else TriangleView.Invalidate; end; @@ -665,15 +645,16 @@ begin begin cp.zoom := 0; cp.CalcBoundbox; - end +{ end else begin cp.zoom := MainCp.zoom; cp.center[0] := MainCp.Center[0]; cp.center[1] := MainCp.Center[1]; +} end; + cp.cmap := MainCp.cmap; -// Render.Compatibility := compatibility; Render.SetCP(cp); Render.Render; PreviewImage.Picture.Bitmap.Assign(Render.GetImage); @@ -830,6 +811,7 @@ end; procedure TEditForm.UpdateFlameX; begin cp.GetFromTriangles(MainTriangles, Transforms); + if not chkPreserve.checked then cp.ComputeWeights(MainTriangles, Transforms); DrawPreview; ShowSelectedInfo; @@ -838,23 +820,26 @@ end; procedure TEditForm.UpdateFlame(DrawMain: boolean); begin -//; MainForm.StopThread; StatusBar.Panels[2].Text := Format('Zoom: %f', [GraphZoom]); + cp.GetFromTriangles(MainTriangles, LastTriangle); + // if not chkPreserve.Checked then ComputeWeights(cp, MainTriangles, transforms); DrawPreview; ShowSelectedInfo; TriangleView.Refresh; if DrawMain then begin MainForm.StopThread; - MainCp.Copy(cp); + + MainCp.Copy(cp, true); + MainCp.cmap := cmap; if mnuResetLoc.checked then begin MainCp.zoom := 0; MainForm.center[0] := cp.center[0]; MainForm.center[1] := cp.center[1]; end; -// if AdjustForm.Visible then AdjustForm.UpdateDisplay; + if AdjustForm.Visible then AdjustForm.UpdateDisplay; if MutateForm.Visible then MutateForm.UpdateDisplay; MainForm.RedrawTimer.enabled := true; end; @@ -1051,7 +1036,10 @@ var tps: TPenStyle; label DrawCorner; begin - assert(SelectedTriangle >= 0); + if (SelectedTriangle < 0) then begin + assert(false, 'Selected triangle < 0'); + SelectedTriangle := 0; + end; assert(TCustomDrawControl(Sender) = TriangleView); if SelectedTriangle > LastTriangle then SelectedTriangle := LastTriangle; @@ -1133,11 +1121,11 @@ begin begin if i <> SelectedTriangle then Pen.Style := psDot; +// this is still a hack -------------------------------------------------------- with cp.xform[i] do if (p[0,0]<>1) or (p[0,1]<>0) or(p[1,0]<>0) or (p[1,1]<>1) or (p[2,0]<>0) or (p[2,1]<>0) then begin Pen.Color := GetTriangleColor(i) shr 1 and $7f7f7f; - //Pen.Mode := pmMerge; a:=toscreen(p[0,0] - p[1,0] + p[2,0], -p[0,1] + p[1,1] - p[2,1]); moveto(a.x, a.y); b:=toscreen(p[0,0] + p[1,0] + p[2,0], -p[0,1] - p[1,1] - p[2,1]); @@ -1268,7 +1256,6 @@ end; end; end; - //i := min( min(Width, Height), integer(round(dmax * sc))); i := integer(round(d * sc)); if i > 4 then begin @@ -1469,11 +1456,6 @@ procedure TEditForm.FormCreate(Sender: TObject); var i: integer; begin - Screen.Cursors[crEditArrow] := LoadCursor(HInstance, 'ARROW_WHITE'); - Screen.Cursors[crEditMove] := LoadCursor(HInstance, 'MOVE_WB'); - Screen.Cursors[crEditRotate] := LoadCursor(HInstance, 'ROTATE_WB'); - Screen.Cursors[crEditScale] := LoadCursor(HInstance, 'SCALE_WB'); - // Custom control setup TriangleView := TCustomDrawControl.Create(self); TriangleView.TabStop := True; @@ -1499,21 +1481,10 @@ begin for i:= 0 to NRVAR - 1 do begin VEVars.InsertRow(Varnames(i), '0', True); end; - for i:= 0 to GetNrVariableNames - 1 do begin vleVariables.InsertRow(GetVariableNameAt(i), '0', True); end; -{ - with vleVariables.ItemProps['blur2_type'] do begin // temporary hack? - ReadOnly := true; - PickList.Add('gaussian'); - PickList.Add('zoom'); - PickList.Add('radial'); - PickList.Add('defocus'); - end; -} - GraphZoom := 1; case EditPrevQual of @@ -1559,8 +1530,6 @@ procedure TEditForm.FormDestroy(Sender: TObject); begin cp.free; Render.free; - -// vleVariables.ItemProps['blur2_type'].Destroy; // :-/ end; procedure TEditForm.TriangleViewMouseMove(Sender: TObject; Shift: TShiftState; @@ -2178,6 +2147,7 @@ begin EditPopup.Popup(mousepos.x, mousepos.y) else begin SelectedTriangle := mouseOverTriangle; + cbTransforms.ItemIndex := SelectedTriangle; TriangleView.Refresh; TrianglePopup.Popup(mousepos.x, mousepos.y) end; @@ -2789,7 +2759,9 @@ begin end; end; end; + cp.TrianglesFromCP(MainTriangles); + ShowSelectedInfo; UpdateFlame(true); end; @@ -3043,8 +3015,6 @@ begin TValueListEditor(Sender).Row := cell.Y; -// if ((Sender = vleVariables) and vleVariables.ItemProps[varDragIndex].ReadOnly) then exit; - Screen.Cursor := crHSplit; GetCursorPos(mousepos); // hmmm @@ -3134,26 +3104,31 @@ end; procedure TEditForm.VEVarsDblClick(Sender: TObject); var n: integer; + v, v1: double; + changed: boolean; begin n := TValueListEditor(Sender).Row - 1; assert(n >= 0); assert(n < TValueListEditor(Sender).rowCount); - if {(varDragOld >= TValueListEditor(Sender).ColWidths[0]) or} - (TValueListEditor(Sender).Values[VarNames(n)] = '0') then exit; + changed := false; - MainForm.UpdateUndo; if Sender = VEVars then begin - cp.xform[SelectedTriangle].vars[n] := 0; - VEVars.Values[VarNames(n)] := '0'; + v := cp.xform[SelectedTriangle].vars[n]; + cp.xform[SelectedTriangle].vars[n] := IfThen(DoubleClickSetVars and (v = 0), 1, 0); + //VEVars.Values[VarNames(n)] := '0'; + changed := (cp.xform[SelectedTriangle].vars[n] <> v); end else begin - //v := 0; // hmm + cp.xform[SelectedTriangle].GetVariable(vleVariables.Keys[n + 1], v); cp.xform[SelectedTriangle].ResetVariable(vleVariables.Keys[n + 1]); //vleVariables.Values[vleVariables.Keys[varDragIndex+1]] := '0'; + cp.xform[SelectedTriangle].GetVariable(vleVariables.Keys[n + 1], v1); + changed := (v1 <> v); end; + if changed then MainForm.UpdateUndo; UpdateFlame(true); end; @@ -3747,6 +3722,11 @@ begin cp.xform[1].color := 1; cp.xform[2].symmetry := 1; + cp.center[0] := 0; + cp.center[1] := 0; + cp.zoom := 0; + cp.pixels_per_unit := PreviewImage.Width/4; + Transforms := 2; SelectedTriangle := 1; MainTriangles[0] := MainTriangles[-1]; @@ -3760,6 +3740,7 @@ begin cbTransforms.Items.Add('1'); cbTransforms.Items.Add('2'); AutoZoom; + UpdateFlame(True); end; @@ -3787,6 +3768,7 @@ begin MainForm.UpdateUndo; cp.xform[SelectedTriangle].c[1][0] := 0; cp.xform[SelectedTriangle].c[1][1] := 1; + cp.TrianglesFromCP(MainTriangles); UpdateFlame(True); end; @@ -3799,6 +3781,7 @@ begin MainForm.UpdateUndo; cp.xform[SelectedTriangle].c[2][0] := 0; cp.xform[SelectedTriangle].c[2][1] := 0; + cp.TrianglesFromCP(MainTriangles); UpdateFlame(True); end; @@ -4062,7 +4045,7 @@ begin end; // this function is temporary................................................... -procedure TEditForm.btnSwapXformsClick(Sender: TObject); +procedure TEditForm.btnPostTriangleClick(Sender: TObject); var i, j: integer; t: double; diff --git a/2.10/Source/FormRender.dfm b/2.10/Source/FormRender.dfm index f08ac95..46c323b 100644 --- a/2.10/Source/FormRender.dfm +++ b/2.10/Source/FormRender.dfm @@ -3,7 +3,7 @@ object RenderForm: TRenderForm Top = 336 BorderIcons = [biSystemMenu, biMinimize] BorderStyle = bsSingle - Caption = 'RenderForm' + Caption = 'Render to Disk' ClientHeight = 449 ClientWidth = 434 Color = clBtnFace @@ -133,7 +133,7 @@ object RenderForm: TRenderForm Width = 137 Height = 17 Alignment = taLeftJustify - Caption = 'Save incomplete render' + Caption = 'Save incomplete renders' TabOrder = 8 OnClick = chkSaveIncompleteRendersClick end @@ -143,9 +143,11 @@ object RenderForm: TRenderForm Width = 433 Height = 353 ActivePage = TabSettings + Images = MainForm.Buttons TabOrder = 9 object TabSettings: TTabSheet Caption = 'Settings' + ImageIndex = 18 object GroupBox5: TGroupBox Left = 8 Top = 8 @@ -542,7 +544,7 @@ object RenderForm: TRenderForm end object TabOutput: TTabSheet Caption = 'Output' - ImageIndex = 1 + ImageIndex = 38 object Output: TMemo Left = 8 Top = 8 diff --git a/2.10/Source/FormRender.pas b/2.10/Source/FormRender.pas index d4b6806..f69e5aa 100644 --- a/2.10/Source/FormRender.pas +++ b/2.10/Source/FormRender.pas @@ -101,7 +101,6 @@ type oldProg: double; ApproxSamples: int64; - SaveIncompleteRenders: boolean; procedure DoPostProcess; @@ -129,9 +128,6 @@ type procedure ResetControls; end; -const - ShowRenderStats = true; - var RenderForm: TRenderForm; Ratio: double; @@ -139,7 +135,8 @@ var implementation uses - Main, Global, SavePreset, formPostProcess, pngimage; + Main, Global, SavePreset, formPostProcess, PngImage, ImageMaker, + Tracer; {$R *.DFM} @@ -191,39 +188,26 @@ begin )]); end; -function TimeToString(t: TDateTime): string; -var - n: integer; +procedure Trace2(const str: string); begin - n := Trunc(t); - Result := ''; - if n>0 then begin - Result := Result + Format(' %d day', [n]); - if (n mod 10) <> 1 then Result := Result + 's'; - end; - t := t * 24; - n := Trunc(t) mod 24; - if n>0 then begin - Result := Result + Format(' %d hour', [n]); - if (n mod 10) <> 1 then Result := Result + 's'; - end; - t := t * 60; - n := Trunc(t) mod 60; - if n>0 then begin - Result := Result + Format(' %d minute', [n]); - if (n mod 10) <> 1 then Result := Result + 's'; - end; - t := t * 60; - t := t - (Trunc(t) div 60) * 60; - Result := Result + Format(' %.2f seconds', [t]); + if TraceLevel >= 2 then + RenderForm.Output.Lines.Add('. . ' + str); end; procedure TRenderForm.HandleThreadCompletion(var Message: TMessage); -var - Stats: TBucketStats; begin + Trace2(MsgComplete + IntToStr(message.LParam)); + if not assigned(Renderer) then begin + Trace2(MsgNotAssigned); + exit; + end; + if Renderer.ThreadID <> message.LParam then begin + Trace2(MsgAnotherRunning); + exit; + end; + EndTime := Now; -// Output.Lines.Add(TimeToStr(EndTime) + ' : Saving image'); + try Renderer.SaveImage(FileName); except @@ -236,26 +220,13 @@ begin else sndPlaySound(pchar(SND_ALIAS_SYSTEMASTERISK), SND_ALIAS_ID or SND_NOSTOP or SND_ASYNC); - if ShowRenderStats then with Stats do - with Output.Lines do - begin - Add(''); - Add('Render Statistics:'); - Add(Format(' Max possible bits: %2.3f', [8 + log2(ApproxSamples)])); - Renderer.GetBucketStats(Stats); - Add(Format(' Max Red: %2.3f bits (%u)', [log2(MaxR), MaxR])); - Add(Format(' Max Green: %2.3f bits (%u)', [log2(MaxG), MaxG])); - Add(Format(' Max Blue: %2.3f bits (%u)', [log2(MaxB), MaxB])); - Add(Format(' Max Count: %2.3f bits (%u)', [log2(MaxA), MaxA])); - Add(Format(' Point hit ratio: %2.2f%%', [100.0*(TotalA/TotalSamples)])); - if RenderTime > 0 then // hmm - Add(Format(' Average speed: %n points per second', [TotalSamples / (RenderTime * 24 * 60 * 60)])); - Add(' Rendering time:' + TimeToString(RenderTime)); - Add(' Total time:' + TimeToString(EndTime - StartTime)); - end; - - Output.Lines.Add(''); PageCtrl.TabIndex := 1; + if ShowRenderStats then + Renderer.ShowBigStats + else + Renderer.ShowSmallStats; + Output.Lines.Add(' Total time:' + TimeToString(EndTime - StartTime)); + Output.Lines.Add(''); if not chkLimitMem.Checked and cbPostProcess.checked then DoPostProcess; @@ -269,21 +240,29 @@ end; procedure TRenderForm.HandleThreadTermination(var Message: TMessage); begin - if Assigned(Renderer) then - begin - Output.Lines.Add(TimeToStr(Now) + ' : Rendering terminated!'); - sndPlaySound(pchar(SND_ALIAS_SYSTEMEXCLAMATION), SND_ALIAS_ID or SND_NOSTOP or SND_ASYNC); + Trace2(MsgTerminated + IntToStr(message.LParam)); + if not assigned(Renderer) then begin + Trace2(MsgNotAssigned); + exit; + end; + if Renderer.ThreadID <> message.LParam then begin + Trace2(MsgAnotherRunning); + exit; + end; + + Output.Lines.Add(TimeToStr(Now) + ' : Rendering terminated!'); + sndPlaySound(pchar(SND_ALIAS_SYSTEMEXCLAMATION), SND_ALIAS_ID or SND_NOSTOP or SND_ASYNC); (* if SaveIncompleteRenders and not chkLimitMem.Checked then begin Output.Lines.Add('Saving incomplete image...'); Renderer.SaveImage(FileName); end; - Output.Lines.Add(''); *) - Renderer.Free; - Renderer := nil; - ResetControls; - end; + Output.Lines.Add(''); + + Renderer.Free; + Renderer := nil; + ResetControls; end; procedure TRenderForm.OnProgress(prog: double); @@ -317,9 +296,6 @@ begin edt := edt + dt; if (edt > 1/24/60/60/2) and (prog > 0) then begin -// Remainder := Min(Remainder, Elapsed * (power(1 / prog, 1.2) - 1)); // --Z-- this power() is weird -// Remaining := Elapsed/prog - Elapsed; // --Z-- should've been like this maybe? ;) too easy anyway... - Remaining := (1 - prog) * edt / (prog - oldProg); edt := 0; oldProg := prog; @@ -330,7 +306,6 @@ begin Trunc(Remaining * 24 * 60 * 60) mod 60, Trunc(Remaining * 24 * 60 * 60 * 100) mod 100]); end; - StatusBar.Panels[2].text := 'Slice ' + IntToStr(Renderer.Slice + 1) + ' of ' + IntToStr(Renderer.nrSlices); end; @@ -364,8 +339,12 @@ begin if (not chkLimitMem.checked) and (ApproxMemory > PhysicalMemory) then begin - Application.MessageBox('You do not have enough memory for this render. Please use memory limiting.', 'Apophysis', 48); - exit; + //Application.MessageBox('You do not have enough memory for this render. Please use memory limiting.', 'Apophysis', 48); + if Application.MessageBox('There is not enough memory for this render. ' + + 'You can use memory limiting, or if you are sure that your system has this much RAM, ' + + 'you can try to allocate memory anyway. ' + + 'Dou you want to try? (USE ON YOUR OWN RISK!!!)', 'Apophysis', + MB_YESNO) <> IDYES then exit; end; if chkLimitMem.checked and (PhysicalMemory < StrToInt(cbMaxMemory.text)) and (Approxmemory > PhysicalMemory) then begin Application.MessageBox('You do not have enough memory for this render. Please use a lower Maximum memory setting.', 'Apophysis', 48); @@ -414,10 +393,8 @@ begin end; if chkLimitMem.checked then begin - try - MaxMemory := StrToInt(cbMaxMemory.text); - if MaxMemory <= 0 then raise Exception.Create(''); - except + MaxMemory := StrToIntDef(cbMaxMemory.text, 0); + if MaxMemory * 1024*1024 < ImageWidth * (int64(ImageHeight) * 4 + oversample) then begin Application.MessageBox('Invalid maximum memory value', 'Apophysis', 16); exit; end; @@ -442,10 +419,10 @@ begin btnPause.enabled := true; btnCancel.Caption := 'Stop'; StartTime := Now; -// Remaining := 365; PageCtrl.TabIndex := 1; + if Output.Lines.Count >= 1000 then Output.Lines.Clear; Output.Lines.Add('--- Rendering "' + ExtractFileName(FileName) + '" ---'); Output.Lines.Add(Format(' Size: %dx%d', [ImageWidth, ImageHeight])); Output.Lines.Add(Format(' Quality: %g', [sample_density])); @@ -462,7 +439,7 @@ begin end; if Assigned(Renderer) then begin - Output.Lines.Add(TimeToStr(Now) + 'Shutting down previous render...'); // hmm + Output.Lines.Add(TimeToStr(Now) + 'Shutting down previous render'); // hmm...? Renderer.Terminate; Renderer.WaitFor; Renderer.Free; @@ -517,7 +494,7 @@ procedure TRenderForm.FormShow(Sender: TObject); var Registry: TRegistry; begin - { Read posution from registry } + { Read position from registry } Registry := TRegistry.Create; try Registry.RootKey := HKEY_CURRENT_USER; @@ -532,6 +509,7 @@ begin finally Registry.Free; end; + SaveDialog.FileName := Filename; case renderFileFormat of 1: txtFilename.Text := ChangeFileExt(SaveDialog.Filename, '.bmp'); @@ -540,8 +518,8 @@ begin end; txtOversample.Text := IntToStr(renderOversample); txtFilterRadius.Text := FloatToStr(renderFilterRadius); - cbWidth.Text := IntToStr(MainForm.Image.Width); - cbHeight.Text := IntToStr(MainForm.Image.Height); + cbWidth.Text := IntToStr(cp.Width); + cbHeight.Text := IntToStr(cp.Height); ImageWidth := StrToInt(cbWidth.Text); ImageHeight := StrToInt(cbHeight.Text); sample_density := renderDensity; @@ -550,6 +528,7 @@ begin cbBitsPerSample.ItemIndex := BitsPerSample; ShowMemoryStatus; Ratio := ImageWidth / ImageHeight; + chkSaveIncompleteRenders.Checked := SaveIncompleteRenders; end; procedure TRenderForm.txtWidthChange(Sender: TObject); @@ -625,7 +604,7 @@ begin end; if SaveIncompleteRenders and not ChkLimitMem.Checked then begin - Renderer.Break; + Renderer.BreakRender; Renderer.WaitFor; //? end else begin @@ -639,12 +618,12 @@ begin end; procedure TRenderForm.txtDensityChange(Sender: TObject); +var + t: double; begin - try - Sample_Density := StrToFloat(txtDensity.Text); - except - end; - ShowMemoryStatus; + if TryStrToFloat(txtDensity.Text, t) then + Sample_Density := t; + if Sample_Density > 0 then ShowMemoryStatus; end; procedure TRenderForm.txtFilterRadiusChange(Sender: TObject); @@ -785,6 +764,7 @@ var i, p: integer; Title: string; FStrings: TStringList; + f: textfile; begin FStrings := TStringList.Create; try diff --git a/2.10/Source/ImageMaker.pas b/2.10/Source/ImageMaker.pas index 81e650c..f8f96c1 100644 --- a/2.10/Source/ImageMaker.pas +++ b/2.10/Source/ImageMaker.pas @@ -43,10 +43,6 @@ type procedure CreateFilter; procedure NormalizeFilter; - procedure SetOnProgress(const Value: TOnProgress); - - procedure Progress(value: double); - public constructor Create; @@ -68,7 +64,7 @@ type property OnProgress: TOnProgress read FOnProgress - write SetOnProgress; + write FOnProgress; end; implementation @@ -234,12 +230,6 @@ begin Fcp := CP; end; -/////////////////////////////////////////////////////////////////////////////// -procedure TImageMaker.SetOnProgress(const Value: TOnProgress); -begin - FOnProgress := Value; -end; - /////////////////////////////////////////////////////////////////////////////// procedure TImageMaker.CreateImage(YOffset: integer); var @@ -313,7 +303,9 @@ begin by := 0; for i := 0 to fcp.Height - 1 do begin bx := 0; - Progress(i / fcp.Height); + + if (i and $7 = 0) and assigned(FOnProgress) then FOnProgress(i / fcp.Height); + AlphaRow := PByteArray(FAlphaBitmap.scanline[YOffset + i]); Row := PRGBArray(FBitmap.scanline[YOffset + i]); for j := 0 to fcp.Width - 1 do begin @@ -451,7 +443,7 @@ zero_alpha: FBitmap.PixelFormat := pf24bit; - Progress(1); + if assigned(FOnProgress) then FOnProgress(1); end; /////////////////////////////////////////////////////////////////////////////// @@ -520,13 +512,6 @@ BMPHack: end; end; -/////////////////////////////////////////////////////////////////////////////// -procedure TImageMaker.Progress(value: double); -begin - if assigned(FOnprogress) then - FOnprogress(Value); -end; - /////////////////////////////////////////////////////////////////////////////// function TImageMaker.GetTransparentImage: TPngObject; var diff --git a/2.10/Source/Main.pas b/2.10/Source/Main.pas index ace7bd1..5fb8763 100644 --- a/2.10/Source/Main.pas +++ b/2.10/Source/Main.pas @@ -1,6 +1,6 @@ { Apophysis Copyright (C) 2001-2004 Mark Townsend - Apophysis Copyright (C) 2005-2006 Ronald Hordijk, Piotr Borys, Peter Sdobnov + Apophysis Copyright (C) 2005-2006 Ronald Hordijk, Piotr Borys, Peter Sdobnov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,10 +25,12 @@ interface uses Windows, Forms, Dialogs, Menus, Controls, ComCtrls, - ToolWin, StdCtrls, Classes, Messages, ExtCtrls, ImgList, controlpoint, - Jpeg, SyncObjs, SysUtils, ClipBrd, Graphics, Math, Global, - Registry, RenderThread, Cmap, ExtDlgs, AppEvnts, ShellAPI, - LibXmlParser, LibXmlComps, Xform, XFormMan, PngImage; + ToolWin, StdCtrls, Classes, Messages, ExtCtrls, ImgList, + Jpeg, SyncObjs, SysUtils, ClipBrd, Graphics, Math, + ExtDlgs, AppEvnts, ShellAPI, Registry, + Global, Xform, XFormMan, ControlPoint, CMap, + RenderThread, RenderTypes, + LibXmlParser, LibXmlComps, PngImage; const PixelCountMax = 32768; @@ -37,10 +39,11 @@ const RS_XO = 2; RS_VO = 3; - AppVersionString = 'Apophysis 2.05 pre-release 12'; + AppVersionString = 'Apophysis 2.05 pre-release 15'; type - TMouseMoveState = (msUsual, msZoomWindow, msZoomOutWindow, msZoomWindowMove, msZoomOutWindowMove, msDrag, msDragMove, msRotate, msRotateMove); + TMouseMoveState = (msUsual, msZoomWindow, msZoomOutWindow, msZoomWindowMove, + msZoomOutWindowMove, msDrag, msDragMove, msRotate, msRotateMove); type TWin32Version = (wvUnknown, wvWin95, wvWin98, wvWinNT, wvWin2000, wvWinXP); @@ -75,7 +78,7 @@ type mnuItemDelete: TMenuItem; mnuListRename: TMenuItem; DisplayPopup: TPopupMenu; - mnuPopCopyUPR: TMenuItem; + mnuPopFullscreen: TMenuItem; RedrawTimer: TTimer; mnuVar: TMenuItem; mnuVRandom: TMenuItem; @@ -175,6 +178,8 @@ type tbQualityBox: TComboBox; View1: TMenuItem; tbShowAlpha: TToolButton; + tbShowTrace: TToolButton; + ToolButton2: TToolButton; procedure tbzoomoutwindowClick(Sender: TObject); procedure mnuimageClick(Sender: TObject); procedure mnuExitClick(Sender: TObject); @@ -270,18 +275,28 @@ type procedure tbQualityBoxSet(Sender: TObject); procedure ImageDblClick(Sender: TObject); procedure tbShowAlphaClick(Sender: TObject); - + procedure tbShowTraceClick(Sender: TObject); + procedure XmlScannerContent(Sender: TObject; Content: String); + private Renderer: TRenderThread; FMouseMoveState: TMouseMoveState; FSelectRect: TRect; + DrawSelection: boolean; FRotateAngle: double; + FClickPos: TPoint; FClickAngle: double; FViewImage: TPngObject; - FViewPos: TPoint; + FViewPos, FViewOldPos: TSPoint; FViewScale: double; + // For parsing: + FinalXformLoaded: boolean; + ActiveXformSet: integer; + XMLPaletteFormat: string; + XMLPaletteCount: integer; + procedure DrawImageView; procedure DrawZoomWindow(ARect: TRect); procedure DrawRotatelines(Angle: double); @@ -294,13 +309,13 @@ type message WM_THREAD_COMPLETE; procedure HandleThreadTermination(var Message: TMessage); message WM_THREAD_TERMINATE; + public { Public declarations } UndoIndex, UndoMax: integer; Center: array[0..1] of double; MainZoom: double; StartTime: TDateTime; - Remainder: TDateTime; AnimPal: TColorMap; VarMenus: array of TMenuItem; @@ -313,6 +328,7 @@ type function SaveXMLFlame(const cp1: TControlPoint; title, filename: string): boolean; procedure DisplayHint(Sender: TObject); procedure OnProgress(prog: double); + procedure ResizeImage; procedure DrawFlame; procedure UpdateUndo; procedure LoadUndoFlame(index: integer; filename: string); @@ -348,7 +364,6 @@ procedure UnpackVariations(v: int64); procedure MultMatrix(var s: TMatrix; const m: TMatrix); procedure ListFlames(FileName: string; sel: integer); procedure ListIFS(FileName: string; sel: integer); -//procedure AdjustScale(var cp1: TControlPoint; width, height: integer); procedure NormalizeVariations(var cp1: TControlPoint); function GetWinVersion: TWin32Version; @@ -356,22 +371,22 @@ var MainForm: TMainForm; pname, ptime: string; nxform: integer; - FinalXformLoaded: boolean; // - ParseCp: TControlPoint; // For parsing; - ActiveXformSet: integer; // + MainCp: TControlPoint; + ParseCp: TControlPoint; + implementation - uses {$IFDEF DEBUG} - JclDebug, ExceptForm, + JclDebug, ExceptForm, {$ENDIF} Editor, Options, Regstry, Render, FullScreen, FormRender, Mutate, Adjust, Browser, Save, About, CmapData, HtmlHlp, ScriptForm, FormFavorites, FormExport, msMultiPartFormData, - ImageColoring, RndFlame; + ImageColoring, RndFlame, + Tracer; {$R *.DFM} @@ -832,7 +847,7 @@ end; procedure TMainForm.OnProgress(prog: double); var - Elapsed: TDateTime; + Elapsed, Remaining: TDateTime; begin Elapsed := Now - StartTime; StatusBar.Panels[0].Text := Format('Elapsed %2.2d:%2.2d:%2.2d.%2.2d', @@ -840,14 +855,16 @@ begin Trunc((Elapsed * 24 - Trunc(Elapsed * 24)) * 60), Trunc((Elapsed * 24 * 60 - Trunc(Elapsed * 24 * 60)) * 60), Trunc((Elapsed * 24 * 60 * 60 - Trunc(Elapsed * 24 * 60 * 60)) * 100)]); - if prog > 0 then - Remainder := Min(Remainder, Elapsed * (power(1 / prog, 1.2) - 1)); + if prog > 0 then + Remaining := Elapsed/prog - Elapsed + else + Remaining := 0; StatusBar.Panels[1].Text := Format('Remaining %2.2d:%2.2d:%2.2d.%2.2d', - [Trunc(Remainder * 24), - Trunc((Remainder * 24 - Trunc(Remainder * 24)) * 60), - Trunc((Remainder * 24 * 60 - Trunc(Remainder * 24 * 60)) * 60), - Trunc((Remainder * 24 * 60 * 60 - Trunc(Remainder * 24 * 60 * 60)) * 100)]); + [Trunc(Remaining * 24), + Trunc((Remaining * 24 - Trunc(Remaining * 24)) * 60), + Trunc((Remaining * 24 * 60 - Trunc(Remaining * 24 * 60)) * 60), + Trunc((Remaining * 24 * 60 * 60 - Trunc(Remaining * 24 * 60 * 60)) * 100)]); StatusBar.Panels[2].Text := MainCp.name; Application.ProcessMessages; end; @@ -1271,16 +1288,14 @@ function ColorToXmlCompact(cp1: TControlPoint): string; var i: integer; begin - Result := ' '; for i := 0 to 255 do begin - Result := Result + '00' //IntToHex(0,2) - + IntToHex(cp1.cmap[i, 0],2) + if ((i and 7) = 0) then Result := Result + #13#10 + ' '; + Result := Result + IntToHex(cp1.cmap[i, 0],2) + IntToHex(cp1.cmap[i, 1],2) + IntToHex(cp1.cmap[i, 2],2); - if ((i and 7) = 7) and (i <> 255) then Result := Result + #13#10 + ' '; end; - Result := Result + '"/>'; + Result := Result + #13#10 + ' '; end; @@ -1323,7 +1338,7 @@ begin if Trim(SheepURL) <> '' then url := 'url="' + Trim(SheepURL) + '" '; } try - parameters := ''; + parameters := 'version="' + AppVersionString + '" '; if cp1.time <> 0 then parameters := parameters + format('time="%g" ', [cp1.time]); @@ -1684,70 +1699,171 @@ end; { ****************************** Display ************************************ } -procedure TMainForm.HandleThreadCompletion(var Message: TMessage); +procedure Trace1(const str: string); begin - if not Assigned(Renderer) then exit; + if TraceLevel >= 1 then + TraceForm.MainTrace.Lines.Add('. ' + str); +end; + +procedure Trace2(const str: string); +begin + if TraceLevel >= 2 then + TraceForm.MainTrace.Lines.Add('. . ' + str); +end; + +procedure TMainForm.HandleThreadCompletion(var Message: TMessage); +var + oldscale: double; +begin + Trace2(MsgComplete + IntToStr(message.LParam)); + if not Assigned(Renderer) then begin + Trace2(MsgNotAssigned); + exit; + end; + if Renderer.ThreadID <> message.LParam then begin + Trace2(MsgAnotherRunning); + exit; + end; + Image.Cursor := crDefault; + + if assigned(FViewImage) then begin + oldscale := FViewImage.Width / Image.Width; + FViewImage.Free; + end + else oldscale := FViewScale; - if assigned(FViewImage) then FViewImage.Free; - FViewPos.X := 0; - FViewPos.Y := 0; - FViewScale := 1; FViewImage := Renderer.GetTransparentImage; - DrawImageView; + if FViewImage <> nil then begin + FViewScale := FViewImage.Width / Image.Width; + + FViewPos.X := FViewScale/oldscale * (FViewPos.X - FViewOldPos.X); + FViewPos.Y := FViewScale/oldscale * (FViewPos.Y - FViewOldPos.Y); + + DrawImageView; +{ + case FMouseMoveState of + msZoomWindowMove: FMouseMoveState := msZoomWindow; + msZoomOutWindowMove: FMouseMoveState := msZoomOutWindow; +// msDragMove: FMouseMoveState := msDrag; + msRotateMove: FMouseMoveState := msRotate; + end; +} + if FMouseMoveState in [msZoomWindowMove, msZoomOutWindowMove, msRotateMove] then + DrawSelection := false; + + Trace1(TimeToStr(Now) + ' : Render complete'); + Renderer.ShowSmallStats; + end + else Trace2('WARNING: No image rendered!'); + + Renderer.WaitFor; + Trace2('Destroying RenderThread #' + IntToStr(Renderer.ThreadID)); Renderer.Free; Renderer := nil; + Trace1(''); end; procedure TMainForm.HandleThreadTermination(var Message: TMessage); begin - if Assigned(Renderer) then begin - Renderer.Free; - Renderer := nil; + Trace2(MsgTerminated + IntToStr(message.LParam)); + if not Assigned(Renderer) then begin + Trace2(MsgNotAssigned); + exit; end; + if Renderer.ThreadID <> message.LParam then begin + Trace2(MsgAnotherRunning); + exit; + end; + Image.Cursor := crDefault; + Trace2(' Render aborted'); + + Trace2('Destroying RenderThread #' + IntToStr(Renderer.ThreadID)); + Renderer.Free; + Renderer := nil; + Trace1(''); end; procedure TMainForm.DrawFlame; +var + GlobalMemoryInfo: TMemoryStatus; // holds the global memory status information + RenderMem: integer; + RenderCP: TControlPoint; + Mem, ApproxMem: cardinal; begin RedrawTimer.Enabled := False; if Assigned(Renderer) then begin assert(Renderer.Suspended = false); + Trace2('Killing previous RenderThread #' + inttostr(Renderer.ThreadID)); Renderer.Terminate; Renderer.WaitFor; + Trace2('Destroying RenderThread #' + IntToStr(Renderer.ThreadID)); + Renderer.Free; Renderer := nil; end; - assert(Renderer = nil); //...? - if not Assigned(Renderer) then begin - if (MainCp.width <> Image.Width) or (MainCp.height <> Image.height) then - begin - MainCp.AdjustScale(Image.width, Image.height); - if EditForm.Visible then EditForm.UpdateDisplay(true); // preview only? - end; + if EditForm.Visible and ((MainCP.Width / MainCP.Height) <> (EditForm.cp.Width / EditForm.cp.Height)) + then EditForm.UpdateDisplay{(true)}; // preview only? if AdjustForm.Visible then AdjustForm.UpdateDisplay(true); // preview only! + + RenderCP := MainCP.Clone; + RenderCp.AdjustScale(Image.width, Image.height); + // following needed ? // cp.Zoom := Zoom; // cp.center[0] := center[0]; // cp.center[1] := center[1]; - MainCp.sample_density := defSampleDensity; - Maincp.spatial_oversample := defOversample; - Maincp.spatial_filter_radius := defFilterRadius; - MainCP.Transparency := true; // always generate transparency data + + RenderCP.sample_density := defSampleDensity; + // oversample and filter are just slowing us down here... + RenderCP.spatial_oversample := 1; // defOversample; + RenderCP.spatial_filter_radius := 0.001; {?} //defFilterRadius; + RenderCP.Transparency := true; // always generate transparency here + + GlobalMemoryInfo.dwLength := SizeOf(GlobalMemoryInfo); + GlobalMemoryStatus(GlobalMemoryInfo); + Mem := GlobalMemoryInfo.dwAvailPhys; + +// if Output.Lines.Count >= 1000 then Output.Lines.Clear; + Trace1('--- Previewing "' + RenderCP.name + '" ---'); + Trace1(Format(' Available memory: %f Mb', [Mem / (1024*1024)])); + ApproxMem := int64(RenderCp.Width) * int64(RenderCp.Height) {* sqr(Oversample)} + * (SizeOfBucket[InternalBitsPerSample] + 4 + 4); // +4 for temp image(s)...? + assert(MainPreviewScale <> 0); + if ApproxMem * sqr(MainPreviewScale) < Mem then begin + if ExtendMainPreview then begin + RenderCP.sample_density := RenderCP.sample_density / sqr(MainPreviewScale); + RenderCP.Width := round(RenderCp.Width * MainPreviewScale); + RenderCP.Height := round(RenderCp.Height * MainPreviewScale); + end; + end + else Trace1('WARNING: Not enough memory for extended preview!'); + if ApproxMem > Mem then + Trace1('OUTRAGEOUS: Not enough memory even for normal preview! :-('); + Trace1(Format(' Size: %dx%d, Quality: %f', + [RenderCP.Width, RenderCP.Height, RenderCP.sample_density])); + FViewOldPos.x := FViewPos.x; + FViewOldPos.y := FViewPos.y; StartTime := Now; - Remainder := 1; try Renderer := TRenderThread.Create; Renderer.TargetHandle := MainForm.Handle; + if TraceLevel > 0 then Renderer.Output := TraceForm.MainTrace.Lines; Renderer.OnProgress := OnProgress; -// Renderer.Compatibility := Compatibility; - Renderer.SetCP(Maincp); + Renderer.SetCP(RenderCP); + + Trace2('Starting RenderThread #' + inttostr(Renderer.ThreadID)); Renderer.Resume; + + Image.Cursor := crAppStart; except + Trace1('ERROR: Cannot start renderer!'); end; + RenderCP.Free; end; end; @@ -1870,7 +1986,6 @@ begin end; end; - procedure TMainForm.mnuOpenClick(Sender: TObject); begin ScriptEditor.Stopped := True; @@ -1970,6 +2085,7 @@ begin RedrawTimer.Enabled := True; tbQualityBox.Text := FloatToStr(defSampleDensity); tbShowAlpha.Down := ShowTransparency; + DrawImageView; UpdateWindows; end; @@ -2339,6 +2455,11 @@ procedure TMainForm.FormCreate(Sender: TObject); var dte: string; begin + Screen.Cursors[crEditArrow] := LoadCursor(HInstance, 'ARROW_WHITE'); + Screen.Cursors[crEditMove] := LoadCursor(HInstance, 'MOVE_WB'); + Screen.Cursors[crEditRotate] := LoadCursor(HInstance, 'ROTATE_WB'); + Screen.Cursors[crEditScale] := LoadCursor(HInstance, 'SCALE_WB'); + {$IFDEF DEBUG} // Enable raw mode (default mode uses stack frames which aren't always generated by the compiler) Include(JclStackTrackingOptions, stRawMode); @@ -2354,7 +2475,7 @@ begin LimitVibrancy := True; Favorites := TStringList.Create; GetScripts; - Compatibility := 1; // for Drave's compatibility +// Compatibility := 1; // for Drave's compatibility Randomize; MainSeed := Random(1234567890); maincp := TControlPoint.Create; @@ -2376,6 +2497,8 @@ begin tbQualityBox.Text := FloatToStr(defSampleDensity); tbShowAlpha.Down := ShowTransparency; + DrawSelection := true; + FViewScale := 1; // prevent divide by zero (?) end; procedure TMainForm.FormShow(Sender: TObject); @@ -2418,6 +2541,14 @@ begin maincp.spatial_filter_radius := defFilterRadius; inc(MainSeed); RandSeed := MainSeed; + +// somehow this doesn't work: +// Image.Width := BackPanel.Width - 2; +// Image.Height := BackPanel.Height - 2; + +// so we'll do it 'bad' way ;-) + Image.Align := alNone; + if FileExists(AppPath + 'default.map') then begin DefaultPalette := GradientBrowser.LoadFractintMap(AppPath + 'default.map'); @@ -2433,7 +2564,7 @@ begin DeleteFile(AppPath + 'apophysis.rand'); if (defFlameFile = '') or (not FileExists(defFlameFile)) then begin - MainCp.Width := image.width; + MainCp.Width := Image.Width; MainCp.Height := Image.Height; RandomBatch; MainForm.Caption := AppVersionString + ' - Random Batch'; @@ -2529,6 +2660,15 @@ end; procedure TMainForm.FormKeyPress(Sender: TObject; var Key: Char); begin + if Key = #27 then begin + case FMouseMoveState of + msZoomWindowMove: FMouseMoveState := msZoomWindow; + msZoomOutWindowMove: FMouseMoveState := msZoomOutWindow; + msDragMove: FMouseMoveState := msDrag; + msRotateMove: FMouseMoveState := msRotate; + end; + DrawImageView; + end; ScriptEditor.Stopped := True; end; @@ -2539,6 +2679,8 @@ begin StopThread; if CanDrawOnResize then reDrawTimer.Enabled := True; + + ResizeImage; DrawImageView; end; @@ -2631,22 +2773,28 @@ begin end; end; -procedure ResizeWindow; +procedure TMainForm.ResizeImage; var - x, y, xdf, ydf: integer; + pw, ph: integer; begin - xdf := MainForm.Width - MainForm.Image.Width; - ydf := MainForm.Height - MainForm.Image.Height; - x := Maincp.Width + xdf; - y := Maincp.height + ydf; - if x <= Screen.width then - MainForm.Width := x - else - MainForm.Width := Screen.Width; - if y <= Screen.height then - MainForm.height := y - else - MainForm.height := Screen.height; + pw := BackPanel.Width - 2; + ph := BackPanel.Height - 2; + begin + if (MainCP.Width / MainCP.Height) > (pw / ph) then + begin + Image.Width := pw; + Image.Height := round(MainCP.Height / MainCP.Width * pw); + Image.Left := 1; + Image.Top := (ph - Image.Height) div 2; + end + else begin + Image.Height := ph; + Image.Width := round(MainCP.Width / MainCP.Height * ph); + Image.Top := 1; + Image.Left := (pw - Image.Width) div 2; + end; + end; + //MainCP.AdjustScale(Image.Width, Image.Height); end; procedure TMainForm.ListViewChange(Sender: TObject; Item: TListItem; @@ -2772,7 +2920,8 @@ begin EntryStrings.free; end; end; - if ResizeOnLoad then ResizeWindow; + {if ResizeOnLoad then} + ResizeImage; end; end; @@ -2865,9 +3014,9 @@ end; procedure TMainForm.ResetLocation; begin maincp.zoom := 0; - maincp.FAngle := 0; - maincp.Width := Image.Width; - maincp.Height := Image.Height; + //maincp.FAngle := 0; + //maincp.Width := Image.Width; + //maincp.Height := Image.Height; maincp.CalcBoundBox; center[0] := maincp.center[0]; center[1] := maincp.center[1]; @@ -2893,6 +3042,8 @@ end; procedure TMainForm.RedrawTimerTimer(Sender: TObject); { Draw flame when timer fires. This seems to stop a lot of errors } begin + if FMouseMoveState in [msZoomWindowMove, msZoomOutWindowMove, msDragMove, msRotateMove] then exit; + RedrawTimer.enabled := False; DrawFlame; end; @@ -3200,6 +3351,7 @@ end; procedure TMainForm.mnuFullScreenClick(Sender: TObject); begin + FullScreenForm.ActiveForm := Screen.ActiveForm; FullScreenForm.Width := Screen.Width; FullScreenForm.Height := Screen.Height; FullScreenForm.Top := 0; @@ -3242,7 +3394,7 @@ begin RenderForm.SaveDialog.FileName := RenderPath + maincp.name + Ext; RenderForm.txtFilename.Text := ChangeFileExt(RenderForm.SaveDialog.Filename, Ext); - RenderForm.cp.Copy(maincp); + RenderForm.cp.Copy(MainCP); RenderForm.cp.cmap := maincp.cmap; RenderForm.zoom := maincp.zoom; RenderForm.Center[0] := center[0]; @@ -3266,9 +3418,37 @@ begin end; procedure TMainForm.mnuResetLocationClick(Sender: TObject); +var + scale: double; + dx, dy, cdx, cdy: double; + sina, cosa: extended; begin UpdateUndo; + + scale := MainCP.pixels_per_unit * power(2, MainCP.zoom); + cdx := MainCP.center[0]; + cdy := MainCP.center[1]; + ResetLocation; + + cdx := MainCP.center[0] - cdx; + cdy := MainCP.center[1] - cdy; + Sincos(MainCP.FAngle, sina, cosa); + if IsZero(sina) then begin + dy := cdy*cosa {- cdx*sina}; + dx := (cdx {+ dy*sina})/cosa; + end + else begin + dx := cdy*sina + cdx*cosa; + dy := (dx*cosa - cdx)/sina; + end; + FViewPos.x := FViewPos.x - dx * scale; + FViewPos.y := FViewPos.y - dy * scale; + + FViewScale := FViewScale * MainCP.pixels_per_unit * power(2, MainCP.zoom) / scale; + + DrawImageView; + RedrawTimer.enabled := true; UpdateWindows; end; @@ -3500,12 +3680,10 @@ begin if FlameInClipboard then begin mnuPaste.enabled := true; -//z btnPaste.enabled := true; end else begin mnuPaste.enabled := false; -//z btnPaste.enabled := false; end; end; @@ -3517,6 +3695,8 @@ begin nxform := 0; FinalXformLoaded := false; ActiveXformSet := 0; + XMLPaletteFormat := ''; + XMLPaletteCount := 0; // Parsecp.cmapindex := -2; // generate palette from cmapindex and hue (apo 1 and earlier) // ParseCp.symmetry := 0; // ParseCP.finalXformEnabled := false; @@ -3547,13 +3727,14 @@ begin end; if FinalXformLoaded = false then begin - MainCP.xform[nxform].Clear; - MainCP.xform[nxform].symmetry := 1; + cp1{MainCP}.xform[nxform].Clear; + cp1{MainCP}.xform[nxform].symmetry := 1; end; if nxform < NXFORMS then for i := nxform to NXFORMS - 1 do cp1.xform[i].density := 0; + // Check for symmetry parameter if ParseCp.symmetry <> 0 then begin @@ -3571,7 +3752,8 @@ begin ParseXML(MainCP, PCHAR(Clipboard.AsText)); Transforms := MainCp.TrianglesFromCP(MainTriangles); Statusbar.Panels[2].Text := MainCp.name; - if ResizeOnLoad then ResizeWindow; + {if ResizeOnLoad then} + ResizeImage; RedrawTimer.Enabled := True; Application.ProcessMessages; UpdateWindows; @@ -3619,15 +3801,6 @@ var Ext, ex, Path: string; cp1: TControlPoint; begin -{ - if (MainCp.NumXForms > 12) or - (MainCP.HasNewVariants) then begin - showMessage('WARNING: This flame will not be correctly rendered '#10#13+ - 'by the flam3 version < 2.7b4.'#10#13+ - 'Please use the 2.7b4 version or newer '#10#13+ - 'or use the internal renderer.'); - end; -} if not FileExists(flam3Path) then begin Application.MessageBox('Renderer does not exist.', 'Apophysis', 16); @@ -3739,6 +3912,50 @@ begin end; end; +//////////////////////////////////////////////////////////////////////////////// + +procedure ParseCompactColors(cp: TControlPoint; count: integer; in_data: string; alpha: boolean = true); + function HexChar(c: Char): Byte; + begin + case c of + '0'..'9': Result := Byte(c) - Byte('0'); + 'a'..'f': Result := (Byte(c) - Byte('a')) + 10; + 'A'..'F': Result := (Byte(c) - Byte('A')) + 10; + else + Result := 0; + end; + end; +var + i, pos, len: integer; + c: char; + data: string; +begin + // diable generating pallete + if Parsecp.cmapindex = -2 then + Parsecp.cmapindex := -1; + + Assert(Count = 256, 'only 256 color Colormaps are supported at the moment'); + data := ''; + for i := 0 to Length(in_data) do + begin + c := in_data[i]; + if c in ['0'..'9']+['A'..'F']+['a'..'f'] then data := data + c; + end; + + if alpha then len := count * 8 + else len := count * 6; + + Assert(len = Length(data), 'Color-data size mismatch'); + + for i := 0 to Count-1 do begin + if alpha then pos := i*8 + 2 + else pos := i*6; + Parsecp.cmap[i][0] := 16 * HexChar(Data[pos + 1]) + HexChar(Data[pos + 2]); + Parsecp.cmap[i][1] := 16 * HexChar(Data[pos + 3]) + HexChar(Data[pos + 4]); + Parsecp.cmap[i][2] := 16 * HexChar(Data[pos + 5]) + HexChar(Data[pos + 6]); + end; +end; + procedure TMainForm.ListXmlScannerStartTag(Sender: TObject; TagName: string; Attributes: TAttrList); begin @@ -3755,7 +3972,7 @@ begin Tokens := TStringList.Create; try - if TagName='xformset' then + if TagName='xformset' then // unused in this release... begin v := Attributes.Value('enabled'); if v <> '' then ParseCP.finalXformEnabled := (StrToInt(v) <> 0) @@ -3836,45 +4053,39 @@ begin v := Attributes.Value('url'); if Trim(v) = '' then v := SheepUrl; Parsecp.URL := v; + end + else if TagName='palette' then + begin + XMLPaletteFormat := Attributes.Value('format'); + XMLPaletteCount := StrToIntDef(Attributes.Value('count'), 256); end; finally Tokens.free; end; end; -procedure ParseCompactcolors(cp: TControlPoint; count: integer; in_data: string); - function HexChar(c: Char): Byte; - begin - case c of - '0'..'9': Result := Byte(c) - Byte('0'); - 'a'..'f': Result := (Byte(c) - Byte('a')) + 10; - 'A'..'F': Result := (Byte(c) - Byte('A')) + 10; - else - Result := 0; - end; - end; -var - i: integer; - c: char; - data: string; +procedure TMainForm.XmlScannerContent(Sender: TObject; Content: String); begin - // diable generating pallete - if Parsecp.cmapindex = -2 then - Parsecp.cmapindex := -1; - - Assert(Count = 256, 'only 256 color Colormaps are supported at the moment'); - data := ''; - for i := 0 to Length(in_data) do + if XMLPaletteCount <= 0 then begin + ShowMessage('ERROR: No colors in palette!'); + exit; + end; + if XMLPaletteFormat = 'RGB' then begin - c := in_data[i]; - if c in ['0'..'9']+['A'..'F']+['a'..'f'] then data := data + c; - end; - Assert((Count * 8) = Length(data), 'Color-data size mismatch'); - for i := 0 to Count -1 do begin - Parsecp.cmap[i][0] := 16 * HexChar(Data[i*8 + 3]) + HexChar(Data[i*8 + 4]); - Parsecp.cmap[i][1] := 16 * HexChar(Data[i*8 + 5]) + HexChar(Data[i*8 + 6]); - Parsecp.cmap[i][2] := 16 * HexChar(Data[i*8 + 7]) + HexChar(Data[i*8 + 8]); + ParseCompactColors(ParseCP, XMLPaletteCount, Content, false); + end + else if XMLPaletteFormat = 'RGBA' then + begin + ParseCompactColors(ParseCP, XMLPaletteCount, Content); + end + else begin + ShowMessage('ERROR: Unsupported palette format!'); + exit; end; + Parsecp.cmapindex := -1; + + XMLPaletteFormat := ''; + XMLPaletteCount := 0; end; procedure TMainForm.XMLScannerEmptyTag(Sender: TObject; TagName: string; @@ -4004,11 +4215,9 @@ end; /////////////////////////////////////////////////////////////////////////////// procedure TMainForm.ImageMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); -var - DestRect: TRect; - SourceRect: TRect; begin if button <> mbLeft then exit; + FClickPos := Point(x, y); case FMouseMoveState of msZoomWindow: begin @@ -4058,7 +4267,7 @@ begin end; msRotate: begin - FClickAngle:=arctan2(y-Image.Height/2, Image.Width/2-x); + FClickAngle := arctan2(y-Image.Height/2, Image.Width/2-x); FRotateAngle := 0; FSelectRect.Left := x; @@ -4070,41 +4279,81 @@ end; /////////////////////////////////////////////////////////////////////////////// procedure TMainForm.ImageMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); +const + snap_angle = 15*pi/180; var - DestRect: TRect; dx, dy: integer; + scale: double; begin +{ + case FMouseMoveState of + msRotate, msRotateMove: + Image.Cursor := crEditRotate; + msDrag, msDragMove: + Image.Cursor := crEditMove; + else + Image.Cursor := crEditArrow; + end; +} case FMouseMoveState of msZoomWindowMove, msZoomOutWindowMove: begin + if DrawSelection then DrawZoomWindow(FSelectRect); + dx := x - FClickPos.X; + dy := y - FClickPos.Y; + + if ssAlt in Shift then begin + if (dy = 0) or (abs(dx/dy) >= Image.Width/Image.Height) then + dy := Round(dx / Image.Width * Image.Height) + else + dx := Round(dy / Image.Height * Image.Width); + FSelectRect.Left := FClickPos.X - dx; + FSelectRect.Top := FClickPos.Y - dy; + FSelectRect.Right := FClickPos.X + dx; + FSelectRect.Bottom := FClickPos.Y + dy; + end + else begin + FSelectRect.Left := FClickPos.X; + FSelectRect.Top := FClickPos.Y; + if (dy = 0) or (abs(dx/dy) >= Image.Width/Image.Height) then begin + FSelectRect.Right := x; + FSelectRect.Bottom := FClickPos.Y + sign(dx*dy) * Round(dx / Image.Width * Image.Height); + end + else begin + FSelectRect.Right := FClickPos.X + sign(dy*dx) * Round(dy / Image.Height * Image.Width); + FSelectRect.Bottom := y; + end; + end; DrawZoomWindow(FSelectRect); - FSelectRect.BottomRight := Point(x, y); - DrawZoomWindow(FSelectRect); + DrawSelection := true; end; msDragMove: begin assert(assigned(FviewImage)); - assert(FViewScale <> 0); - FViewPos.X := FViewPos.X + round( (x - FSelectRect.Right) / FViewScale); - FViewPos.Y := FViewPos.Y + round( (y - FSelectRect.Bottom) / FViewScale); + + scale := FViewScale * Image.Width / FViewImage.Width; + FViewPos.X := FViewPos.X + (x - FSelectRect.Right) / scale; + FViewPos.Y := FViewPos.Y + (y - FSelectRect.Bottom) / scale; FSelectRect.BottomRight := Point(x, y); - DrawImageView; + DrawImageView; end; msRotateMove: begin - DrawRotatelines(FRotateAngle); + if DrawSelection then DrawRotatelines(FRotateAngle); -// FRotateAngle := FRotateAngle + 0.004 * (FSelectRect.Left - X); - FRotateAngle:=arctan2(y-Image.Height/2, Image.Width/2-x) - FClickAngle; + FRotateAngle := arctan2(y-Image.Height/2, Image.Width/2-x) - FClickAngle; + if ssShift in Shift then // angle snap + FRotateAngle := Round(FRotateAngle/snap_angle)*snap_angle; FSelectRect.Left := x; // pdjpointgen.Rotate(FRotateAngle); // FRotateAngle := 0; DrawRotatelines(FRotateAngle); + DrawSelection := true; { Image.Refresh; if AdjustForm.Visible then begin @@ -4119,12 +4368,13 @@ end; /////////////////////////////////////////////////////////////////////////////// procedure TMainForm.ImageMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +var + scale: double; begin case FMouseMoveState of msZoomWindowMove: begin DrawZoomWindow(FSelectRect); - FSelectRect.BottomRight := Point(x, y); FMouseMoveState := msZoomWindow; if (abs(FSelectRect.Left - FSelectRect.Right) < 10) or (abs(FSelectRect.Top - FSelectRect.Bottom) < 10) then @@ -4134,13 +4384,17 @@ begin UpdateUndo; MainCp.ZoomtoRect(FSelectRect); + FViewScale := FViewScale * Image.Width / abs(FSelectRect.Right - FSelectRect.Left); + FViewPos.x := FViewPos.x - ((FSelectRect.Right + FSelectRect.Left) - Image.Width)/2; + FViewPos.y := FViewPos.y - ((FSelectRect.Bottom + FSelectRect.Top) - Image.Height)/2; + DrawImageView; + RedrawTimer.Enabled := True; UpdateWindows; end; msZoomOutWindowMove: begin DrawZoomWindow(FSelectRect); - FSelectRect.BottomRight := Point(x, y); FMouseMoveState := msZoomOutWindow; if (abs(FSelectRect.Left - FSelectRect.Right) < 10) or (abs(FSelectRect.Top - FSelectRect.Bottom) < 10) then @@ -4150,6 +4404,13 @@ begin UpdateUndo; MainCp.ZoomOuttoRect(FSelectRect); + scale := Image.Width / abs(FSelectRect.Right - FSelectRect.Left); + FViewScale := FViewScale / scale; + FViewPos.x := scale * (FViewPos.x + ((FSelectRect.Right + FSelectRect.Left) - Image.Width)/2); + FViewPos.y := scale * (FViewPos.y + ((FSelectRect.Bottom + FSelectRect.Top) - Image.Height)/2); + + DrawImageView; + RedrawTimer.Enabled := True; UpdateWindows; end; @@ -4182,6 +4443,12 @@ begin if MainForm_RotationMode = 0 then MainCp.Rotate(FRotateAngle) else MainCp.Rotate(-FRotateAngle); + if assigned(FViewImage) then begin + FViewImage.Free; + FViewImage := nil; + DrawImageView; + end; + RedrawTimer.Enabled := True; UpdateWindows; end; @@ -4194,6 +4461,13 @@ var i, j: integer; bm: TBitmap; r: TRect; + scale: double; +const + msg = #54; // 'NO PREVIEW'; +var + ok: boolean; + GlobalMemoryInfo: TMemoryStatus; // holds the global memory status information + area: int64; begin bm := TBitmap.Create; bm.Width := Image.Width; @@ -4215,16 +4489,42 @@ begin FillRect(Rect(0, 0, bm.Width, bm.Height)); end; end; + ok := false; if assigned(FViewImage) then begin - FViewScale := Image.Width / FViewImage.Width; + scale := FViewScale * Image.Width / FViewImage.Width; - r.Left := round(FViewScale * FViewPos.X); - r.Right := round(FViewScale * (FViewPos.X + FViewImage.Width)); - r.Top := Image.Height div 2 + round(FViewScale * (FViewPos.Y - FViewImage.Height/2)); - r.Bottom := Image.Height div 2 + round(FViewScale * (FViewPos.Y + FViewImage.Height/2)); + r.Left := Image.Width div 2 + round(scale * (FViewPos.X - FViewImage.Width/2)); + r.Right := Image.Width div 2 + round(scale * (FViewPos.X + FViewImage.Width/2)); + r.Top := Image.Height div 2 + round(scale * (FViewPos.Y - FViewImage.Height/2)); + r.Bottom := Image.Height div 2 + round(scale * (FViewPos.Y + FViewImage.Height/2)); - FViewImage.Draw(bm.Canvas, r); + GlobalMemoryInfo.dwLength := SizeOf(GlobalMemoryInfo); + GlobalMemoryStatus(GlobalMemoryInfo); + area := abs(r.Right - r.Left) * int64(abs(r.Bottom - r.Top)); + + if (area * 4 < GlobalMemoryInfo.dwAvailPhys div 2) or + (area <= Screen.Width*Screen.Height*4) then + try + FViewImage.Draw(bm.Canvas, r); + ok := true; + except + end; end; + + if not ok then + with bm.Canvas do + begin + Font.Name := 'Wingdings'; // 'Arial'; + Font.Height := bm.Height div 4; + Font.Color := $808080; + Brush.Style := bsClear; + i := (bm.Width - TextWidth(msg)) div 2; + j := (bm.Height - TextHeight(msg)) div 2; + Font.Color := 0; + TextOut(i+2,j+2, msg); + Font.Color := clWhite; //$808080; + TextOut(i,j, msg); + end; Image.Picture.Graphic := bm; Image.Refresh; bm.Free; @@ -4391,6 +4691,7 @@ begin end else mnuResetLocationClick(Sender); end; + {$IFDEF DEBUG} /////////////////////////////////////////////////////////////////////////////// procedure TMainForm.AppException(Sender: TObject; E: Exception); @@ -4410,13 +4711,15 @@ end; /////////////////////////////////////////////////////////////////////////////// procedure TMainForm.tbShowAlphaClick(Sender: TObject); -var - DestRect: TRect; - bm: TBitmap; begin ShowTransparency := tbShowAlpha.Down; DrawImageView; end; +procedure TMainForm.tbShowTraceClick(Sender: TObject); +begin + TraceForm.Show; +end; + end. diff --git a/2.10/Source/Preview.pas b/2.10/Source/Preview.pas index 9ab83f8..c184f03 100644 --- a/2.10/Source/Preview.pas +++ b/2.10/Source/Preview.pas @@ -1,5 +1,6 @@ { Apophysis Copyright (C) 2001-2004 Mark Townsend + Apophysis Copyright (C) 2005-2006 Ronald Hordijk, Piotr Borys, Peter Sdobnov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by