Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 05/24/22 in all areas

  1. "RTC SDK was originally developed by Danijel Tkalčec in 2004, and acquired by Teppi Technology in 2018 . Now, as of May 20th 2022, we announce that ReatlThinClient SDK (a.k.a. RTC SDK) is open source." https://rtc.teppi.net/ https://github.com/teppicom/RealThinClient-SDK
  2. This is a pointless endeavor unless you have some proof that the new code in Delphi 11 has a performance regression - the generated assembly code for the purepascal code is almost identical to the handwritten version before on x86 and all other platforms it should be significantly faster than the previous pure pascal implementation. (I should know - I did that change)
  3. corneliusdavid

    Working with Delphi and Excel

    Uh, how do you expect to get the contents of a file without opening it? Or do you mean that you don't want to use OLE? I've used XLSReadWrite successfully.
  4. The PUREPASCAL Pos code in Delphi 11 has been changed to a more optimised version, in fact the same code that the ASM version is based on. Using the PUREPASCAL version even in WIN32 would give the same execution speed as the ASM version.
  5. vfbb

    Rounded polygon

    Here's an example: uses Skia; function MakeCubicSplineInterpolation(const APoints: TArray<TPointF>): ISkPath; var LPathBuilder: ISkPathBuilder; LSegments: Integer; I: Integer; mx: Single; my: Single; LScratches: array of record a, b, c, r, p: TPointF; end; begin LPathBuilder := TSkPathBuilder.Create; if Length(APoints) < 2 then Exit(LPathBuilder.Detach); if Length(APoints) = 2 then begin LPathBuilder.MoveTo(APoints[0]); LPathBuilder.LineTo(APoints[1]); Exit(LPathBuilder.Detach); end; LSegments := Length(APoints) - 1; SetLength(LScratches, LSegments); LScratches[0].a := PointF(0, 0); LScratches[0].b := PointF(2, 2); LScratches[0].c := PointF(1, 1); LScratches[0].r := PointF(APoints[0].X + 2 * APoints[1].X, APoints[0].Y + 2 * APoints[1].Y); for I := 1 to LSegments - 2 do begin LScratches[I].a := PointF(1, 1); LScratches[I].b := PointF(4, 4); LScratches[I].c := PointF(1, 1); LScratches[I].r := PointF(4 * APoints[i].X + 2 * APoints[I + 1].X, 4 * APoints[I].Y + 2 * APoints[I + 1].Y); end; LScratches[LSegments - 1].a := PointF(2, 2); LScratches[LSegments - 1].b := PointF(7, 7); LScratches[LSegments - 1].c := PointF(0, 0); LScratches[LSegments - 1].r := PointF(8 * APoints[LSegments - 1].X + APoints[LSegments].X, 8 * APoints[LSegments - 1].Y + APoints[LSegments].Y); for I := 1 to LSegments - 1 do begin mx := LScratches[I].a.X / LScratches[I - 1].b.X; my := LScratches[I].a.Y / LScratches[I - 1].b.Y; LScratches[I].b := LScratches[I].b - PointF(mx * LScratches[I - 1].c.X, my * LScratches[I - 1].c.Y); LScratches[I].r := LScratches[I].r - PointF(mx * LScratches[I - 1].r.X, my * LScratches[I - 1].r.Y); end; LScratches[LSegments - 1].p := PointF(LScratches[LSegments - 1].r.X / LScratches[LSegments - 1].b.X, LScratches[LSegments - 1].r.Y / LScratches[LSegments - 1].b.Y); for I := Length(APoints) - 3 downto 0 do begin LScratches[I].p := PointF((LScratches[I].r.X - LScratches[I].c.X * LScratches[I + 1].p.X) / LScratches[I].b.X, (LScratches[I].r.Y - LScratches[I].c.Y * LScratches[I + 1].p.Y) / LScratches[I].b.Y); end; LPathBuilder.MoveTo(APoints[0]); for I := 0 to LSegments - 2 do begin LPathBuilder.CubicTo(LScratches[I].p, PointF(2 * APoints[I + 1].X - LScratches[I + 1].p.X, 2 * APoints[I + 1].Y - LScratches[I + 1].p.Y), APoints[I + 1]); end; LPathBuilder.CubicTo(LScratches[LSegments - 1].p, PointF(0.5 * (APoints[LSegments].X + LScratches[LSegments - 1].p.X), 0.5 * (APoints[LSegments].Y + LScratches[LSegments - 1].p.Y)), APoints[LSegments]); Result := LPathBuilder.Detach; end; procedure TForm1.SkPaintBox1Draw(ASender: TObject; const ACanvas: ISkCanvas; const ADest: TRectF; const AOpacity: Single); var LPaint: ISkPaint; LMyPoints: TArray<TPointF>; begin LMyPoints := [PointF(62, 511), PointF(162, 605), PointF(262, 610), PointF(362, 402), PointF(462, 959), PointF(562, 58), PointF(662, 272), PointF(762, 99), PointF(862, 759), PointF(962, 945)]; LPaint := TSkPaint.Create(TSkPaintStyle.Stroke); LPaint.Color := TAlphaColors.Red; LPaint.AntiAlias := True; LPaint.StrokeWidth := 3; LPaint.StrokeCap := TSkStrokeCap.Round; ACanvas.DrawPath(MakeCubicSplineInterpolation(LMyPoints), LPaint); LPaint.StrokeWidth := 10; LPaint.Color := TAlphaColors.Black; ACanvas.DrawPoints(TSkDrawPointsMode.Points, LMyPoints, LPaint); end; Result: Note: You don't need to use Skia, it was just a facilitator for the example.
  6. Mavarik

    Request for advice: FireMonkey and Frames

    That's why I did not use frames at all... But with FMX there is no need for a "frame". For every content I create a Form with a TLayout. If there is any need to uses this content on a other form/tab/whatever, you just have to set the parent of the layout to the e.g. tab or any other layout on any other form. So easy... Frank
  7. You should profile your program to find out where the bottleneck is. Human intuition is usually wrong in such matters.
  8. Lajos Juhász

    pageControl

    In D11 you should check out also TCardPanel its made to replace that hack with TPageControl. Be aware it's not perfect yet will take a couple of versions to remove the bugs.
  9. Mike Torrettinni

    pageControl

    Each TabSheet has a TabVisible property, if you set it to False it will hide that tab. To hide/show a TabSheet there is Visible property. I see that linked documentation in 1 post up is working now. Still wanted to point out the 2 similarly named properties, they could choose better naming.
  10. Der schöne Günther

    pageControl

    Vcl.ComCtrls.TTabSheet.TabVisible - RAD Studio API Documentation (embarcadero.com)
  11. Are you writing both ends of the document exchange system? If you must access an existing system, then you must get the specification of the attachment.
  12. Angus Robertson

    Working with Delphi and Excel

    I've been using Axolot Data XLSReadWrite to read and create XLS and XLSX spreadsheets for almost 20 years. Not free, but just works. http://www.axolot.com/ Angus
  13. You can always extract any function from RTL unit and compile it separately.
  14. David Heffernan

    Working with Delphi and Excel

    No. It is not possible to read an excel file without opening it. However, I suspect that what you actually want to do is to read such a file without using an Excel process via its COM API. If that is what you want to do then it is indeed possible.
  15. If there are faster asm versions in the system unit, that work on x64, then they will be used. But you can't compile an x86 asm procedure in x64 and expect it to work. You need a bespoke x64 version. In other words, I don't think what you describe is going to be possible. What is your specific performance issue?
  16. What is your target platform? If it is Win32, the ASM version will be chosen.
  17. Martybartfast

    Connect to wss://

    Hi again Angus. So I've got Web Sockets working in my application, everything connects as it should, and I can send a welcome message in the Connected event. Problem now is that once the connection is established, if I then send a string to the client(s), the browser immediately disconnects from the Web Socket connection. Delphi: s : string; n : integer; b : integer; ... s := 'Hello'; for n := 0 to WebSocketServer.ClientCount-1 do begin b := WebSocketServer.Client[n].SendStr(s); end; b does indeed show the correct number of characters have been sent. The HTML is taken directly from your sample: function init(){ var host = "ws://127.0.0.1:42071/xcs"; try { socket = new WebSocket(host); log('WebSocket - status '+socket.readyState); socket.onopen = function(msg){ log("Welcome - status "+this.readyState); }; socket.onmessage = function(msg){ log("Received ("+msg.data.length+" bytes): " + (msg.data.length < 5000 ? msg.data : (msg.data.substr(0, 30) + '…'))); }; socket.onclose = function(msg){ log("Disconnected - status "+this.readyState); }; } catch(ex) { log(ex); } } Any idea what I'm doing wrong?
  18. A.M. Hoornweg

    Rounded polygon

    Very interesting, thanks for the link!
  19. angusj

    Rounded polygon

    Here's my GetSmoothPath() routine. It requires no specific graphics library to use, just a few extra functions (also included below). This function generates an array of control points that's very easily converted into a flattened cubic bezier path using just about any 2D graphics library. (nb: The code below has been written with simplicity as the focus rather than performance.) uses SysUtils, Math; type TPointD = record X, Y: double; end; TPathD = array of TPointD; TArrayOfDouble = array of double; function DistanceSqrd(const pt1, pt2: TPointD): double; begin result := Sqr(pt1.X - pt2.X) + Sqr(pt1.Y - pt2.Y); end; function Distance(const pt1, pt2: TPointD): double; begin Result := Sqrt(DistanceSqrd(pt1, pt2)); end; function OffsetPoint(const pt: TPointD; dx, dy: double): TPointD; begin result.x := pt.x + dx; result.y := pt.y + dy; end; function GetAvgUnitVector(const vec1, vec2: TPointD): TPointD; var inverseHypot: Double; begin Result.X := (vec1.X + vec2.X) * 0.5; Result.y := (vec1.Y + vec2.Y) * 0.5; inverseHypot := 1 / Hypot(Result.X, Result.Y); Result.X := Result.X * inverseHypot; Result.Y := Result.Y * inverseHypot; end; procedure MakeSymmetric(var val1, val2: double); begin val1 := (val1 + val2) * 0.5; val2 := val1; end; function GetUnitVector(const pt1, pt2: TPointD): TPointD; var dx, dy, inverseHypot: Double; begin if (pt1.x = pt2.x) and (pt1.y = pt2.y) then begin Result.X := 0; Result.Y := 0; Exit; end; dx := (pt2.X - pt1.X); dy := (pt2.Y - pt1.Y); inverseHypot := 1 / Hypot(dx, dy); dx := dx * inverseHypot; dy := dy * inverseHypot; Result.X := dx; Result.Y := dy; end; // GetSmoothPath - returns cubic bezier control points // parameters: 1. path for smoothing // 2. whether or not the smoothed path will closed // 3. percent smoothness (0..100) // 4. maximum dist control pts from path pts (0 = no limit) // 5. symmetric vs asymmmetric control pts function GetSmoothPath(const path: TPathD; pathIsClosed: Boolean; percentOffset, maxCtrlOffset: double; symmetric: Boolean): TPathD; var i, len, prev: integer; vec: TPointD; pl: TArrayOfDouble; unitVecs: TPathD; d, d1,d2: double; begin Result := nil; len := Length(path); if len < 3 then Exit; d := Max(0, Min(100, percentOffset))/200; if maxCtrlOffset <= 0 then maxCtrlOffset := MaxDouble; SetLength(Result, len *3 +1); prev := len-1; SetLength(pl, len); SetLength(unitVecs, len); for i := 0 to len -1 do begin pl[i] := Distance(path[prev], path[i]); unitVecs[i] := GetUnitVector(path[prev], path[i]); prev := i; end; Result[len*3] := path[0]; for i := 0 to len -1 do begin if i = len -1 then begin vec := GetAvgUnitVector(unitVecs[i], unitVecs[0]); d2 := pl[0]*d; end else begin vec := GetAvgUnitVector(unitVecs[i], unitVecs[i+1]); d2 := pl[i+1]*d; end; d1 := pl[i]*d; if symmetric then MakeSymmetric(d1, d2); if i = 0 then Result[len*3-1] := OffsetPoint(path[i], -vec.X * Min(maxCtrlOffset, d1), -vec.Y * Min(maxCtrlOffset, d1)) else Result[i*3-1] := OffsetPoint(path[i], -vec.X * Min(maxCtrlOffset, d1), -vec.Y * Min(maxCtrlOffset, d1)); Result[i*3] := path[i]; Result[i*3+1] := OffsetPoint(path[i], vec.X * Min(maxCtrlOffset, d2), vec.Y * Min(maxCtrlOffset, d2)); end; if not pathIsClosed then begin Result[1] := Result[0]; dec(len); Result[len*3-1] := Result[len*3]; SetLength(Result, Len*3 +1); end; end; And here's what it produces ... the path to smooth (black), the cubic bezier control path produced by GetSmoothPath() (blue) and the flattened cubic bezier path (2D graphics library of you choice required) (red). var TPathD path; begin path := MakePath([190,120, 260,270, 560,120, 190,490]); path := GetSmoothPath(path, true, 20, 0, false); path := ThirdParty2DGraphicsLibrary.FlattenCBezier(path); end; var TPathD path; begin path := MakePath([190,120, 260,270, 560,120, 190,490]); path := GetSmoothPath(path, true, 80, 0, false); path := ThirdParty2DGraphicsLibrary.FlattenCBezier(path); end; Edit: The best way to avoid intersections is to make sure you have enough data points before generating your curves.
  20. David Heffernan

    Windows APIs?

    Delphi can access all Windows APIs and the best reference is MSDN.
×