Skip to content

Latest commit

 

History

History
1033 lines (805 loc) · 46.1 KB

README.md

File metadata and controls

1033 lines (805 loc) · 46.1 KB

Alcinoe

At the heart of Alcinoe is a belief in empowering developers to create fast, modern, and seamless applications without the typical bottlenecks of complexity or performance limitations. We believe that development should be focused on innovation, not fighting against the constraints of your tools. Alcinoe is built with the philosophy that every developer deserves the best performance, the freedom to customize, and the power to deliver exceptional user experiences across platforms—all while maintaining independence from the dominance of GAFA (Google, Apple, Facebook, Amazon).

Alcinoe is fully compatible with Delphi Athens 12.2. If you find this library helpful, please consider giving it a star on GitHub. It’s free and greatly supports the project’s visibility and growth.

Example of an App Built with Alcinoe

Alcinoe Firemonkey Controls Demo

The Alcinoe FireMonkey Controls Demo highlights the power and flexibility of Alcinoe's UI components. It demonstrates how to build high-performance, visually stunning, and responsive FireMonkey applications with ease, showcasing advanced features and custom styling capabilities.

Alcinoe Firemonkey Controls Demo Alcinoe Firemonkey Controls Demo

KisKis

KisKis is a dating app crafted in Delphi using the Alcinoe framework, offering a sleek, modern, and responsive platform for connecting people. Leveraging Alcinoe's advanced UI controls and optimized performance capabilities, KisKis delivers an engaging and seamless user experience, making meaningful connections more accessible and enjoyable.

Embarcadero Quality Reports

Please request the resolution of these quality reports. Due to the unresolved issues from Embarcadero, we have been forced to apply patches to the original Delphi source files:

Install Alcinoe

To set up Alcinoe, start by running the CompileAll.bat script. This batch file performs a series of tasks, including retrieving and patching the original Delphi source code, downloading the necessary iOS/Android libraries, generating the Alcinoe JAR files, building the BPL (Borland Package Library), compiling the tools in the Tools directory, and finally compiling all demos found in the Demos directory. Please note that some demos require components from devexpress.

If you only need to use Alcinoe's non-visual components, no further steps are necessary. Simply ensure that Source is included in your project's search path.

To use Alcinoe's visual components at design time, you will need to install the BPL. Open Delphi, go to Component > Install Packages..., and select the BPL from Libraries\bpl\Alcinoe. Additionally, include both Source and all subdirectories from Embarcadero\Athens in your search path.

Update Alcinoe

From time to time, we may need to rename units, classes, and functions in Alcinoe. To help you automatically update these names in your project and stay aligned with the latest version of Alcinoe, we provide a tool called CodeRenaming. You can find this tool here: CodeRenaming

Propose a Change on GitHub

If you'd like to suggest changes to the Alcinoe directory, please follow these steps:

  1. Fork the Alcinoe Repository: First, you'll need to fork the repository. Forking creates a personal copy of the Alcinoe source code that you can modify as needed..

    Fork

  2. Make Your Edits: After forking, make the necessary changes to the source code. Then, commit and push these changes to your forked repository.

  3. Submit a Pull Request: Once you're happy with your changes, go to your forked repository, click on 'Contribute,' and select 'Open a pull request' to submit your proposal.

    Contribute


About Skia

Skia is an open-source 2D graphics library that powers the graphics engine used by Flutter and the Android operating system. The implementation of Skia in Delphi marked a significant advancement for the FireMonkey framework, as it greatly surpasses the legacy Delphi TCanvasGPU graphics engine in nearly every aspect.

Key Advantages of Skia:

  • Solid Graphics Foundation: Since Skia is the same graphics engine used by Flutter, apps built with Flutter or Delphi + Skia share the same foundational graphics technology.
  • Performance: The Skia algorithms are optimized to the extent that they can often render directly onto the form surface without requiring an internal buffer.
  • Cross-Platform Consistency: Skia offers a consistent graphics engine across all platforms (Windows, iOS, macOS, Android).
  • Rich Features: Skia provides powerful capabilities typical of a robust graphics engine, including advanced text formatting and shadow rendering.

Drawbacks of Skia:

  • Increased Package Size: Adding Skia increases the package size by approximately 25 MB.
  • Dependency on Google: Skia is a Google product, and while Embarcadero has traditionally focused on offering an independent product free from GAFA domination, using Skia introduces a dependency on Google's technology.
  • OpenGL Limitations: Under OpenGL, only raster images (CPU) can be shared across different threads. This means that GPU textures cannot be created in background threads and later drawn on the main form surface. Interestingly, there seems to be no noticeable speed improvement when drawing GPU images compared to raster images.
  • Image Rendering Performance: While Skia excels at drawing shapes directly on the form surface, it is notably slower (4x more slower) than the legacy Delphi canvas (TCanvasGPU) when rendering images onto the form.

Performance Challenges with Skia:

The slower image rendering is particularly problematic in scenarios where we paint everything first onto an internal buffer and then render that buffer to the form surface on each paint loop—a technique often used to avoid flickering and improve performance. Unfortunately, Skia can be up to 4 times slower at drawing images onto the form surface compared to the legacy Delphi TCanvasGPU, which uses OpenGL textures.

For example, on a Google Pixel 7, I can render 2000 textures simultaneously at 90 FPS using TCanvasGPU. However, with Skia, I can only render 500 images at the same frame rate. You can verify this using the demo app located at Demos/ALFmxGraphics.

The Chosen Approach:

Given these limitations, I’ve decided to use Skia as the backend graphics engine in Alcinoe while continuing to use the legacy Delphi canvas (TCanvasGPU) for rendering on the main form surface. The exception is on Windows, where we use Skia for both the backend and the main form surface.

Platform-Specific Considerations:

On Android and iOS, the operating systems already provide powerful graphics APIs, and in many cases, these native APIs outperform Skia—often by as much as 2x. While the performance of the OS graphics APIs is superior, Skia still offers the benefit of a unified graphics engine across all platforms, along with additional features like animated images.

Material 3 Controls for Delphi: A Modern UI Approach

In recent years, Material Design has emerged as a guiding design language for developers creating modern, user-friendly, and visually appealing applications. With the release of Material You (Material Design 3), Google has taken a step further by allowing greater personalization and a more dynamic appearance. Developers using Delphi can now leverage Material 3 principles to create stunning, cohesive interfaces across platforms like Android, iOS, Windows, and macOS.

Key Alcinoe Controls for Material 3 Design

1. TALButton

TALButton offers full customization for states such as Enabled, Pressed, and Disabled, allowing for modern Material 3 button styles. You can adjust properties like fill, border, shadow, and font to match Material 3’s bold, clear design principles. It supports HTML content, enabling you to easily include icons or rich text.

2. TALCheckBox and TALRadioButton

Both controls follow Material 3’s minimalistic and responsive design. They include customizable properties for checkmark, border, and shadow and utilize smooth transitions between states. Their highly customizable nature allows you to create checkbox and radio button components that align with Material 3’s aesthetic.

4. TALSwitch

TALSwitch is designed for easy customization, allowing you to control the design of the switch in states such as Enabled, Hovered, Focused, Pressed, and Disabled. The control provides smooth, responsive transitions between on and off states, reflecting the fluid, adaptable nature of Material 3’s switches. The customizable design ensures that TALSwitch fits seamlessly into a modern, minimalistic interface, offering both visual appeal and optimized performance for Delphi applications.

3. TALTrackBar and TALRangeTrackBar

TALTrackBar allows for extensive customization of its appearance and behavior, making it an ideal choice for implementing Material 3’s clean and modern slider design. You can easily customize the track and thumb with properties such as fill, stroke, and shadow to achieve the sleek, minimalistic look that defines Material 3. The slider's interactions, including value indicators and stop indicators, are smooth, ensuring responsive feedback as the user interacts with the control. Its transitions between states like Enabled, Focused, and Pressed contribute to a polished, fluid user experience.

4. TALEdit and TALMemo

Alcinoe’s native TALEdit and TALMemo controls are designed to match Material 3’s input fields, offering customizable border, shadow, and font properties. These controls adapt across platforms while maintaining a consistent, clean interface for text input, with features like autosizing and prompt text.

Why Alcinoe for Material 3?

While Material 3 focuses on responsive and adaptive design, performance is equally important. Alcinoe’s double-buffered rendering ensures that your controls are fast and fluid, even during complex UI interactions like scrolling. This performance boost aligns perfectly with Material 3’s goal of seamless, responsive user interfaces.

Incorporating Alcinoe in your Delphi projects allows you to create modern, high-performance apps with a polished Material 3 appearance, without compromising on speed or cross-platform compatibility.

Learn more at Demos/ALFmxControls

High-Performance Text Control with HTML Formatting and Interactive Capabilities

TALText is a robust component similar to TText, but with enhanced capabilities like basic HTML text formatting support. Despite incorporating HTML formatting, TALText delivers substantial performance improvements over TText. This is achieved through its double-buffered engine, which renders text on an internal buffer and then draws only the buffer onto the form during each paint cycle. This design ensures that TALText is extremely fast and efficient. Additionally, TALText enhances functionality by supporting mouse event handling, allowing it to detect specific HTML elements (such as span IDs and bounds) under the mouse pointer. This feature enables interactive text elements, making it ideal for applications requiring dynamic, responsive text behavior. Learn more at Demos/ALFmxControls


Video Player for FireMonkey

ALVideoPlayer renders video onto a texture, allowing seamless integration into a Delphi form while supporting Z-ORDER, enabling controls to be placed on top of the video. In contrast, Delphi’s official video players are native video player windows overlaid on the form, which do not support Z-ORDER.

On Android, Alcinoe uses ExoPlayer, which provides advanced features such as dynamic adaptive streaming over HTTP (DASH), HLS, SmoothStreaming, and common encryption—capabilities not available in MediaPlayer. ExoPlayer is also designed to be easily customizable and extendable. On iOS, AVPlayer is used, offering similar HLS support to ExoPlayer.

video player for FireMonkey video player for FireMonkey video player for FireMonkey

Learn more at Demos/ALFmxControls

WebRTC Delphi Wrapper

WebRTC (Web Real-Time Communications) is a technology that allows web applications and sites to capture and stream audio and/or video media, as well as exchange arbitrary data between browsers and mobile applications without an intermediary. The set of standards behind WebRTC enables peer-to-peer data sharing and teleconferencing without the need for plug-ins or third-party software.

Delphi WebRTC wrapper

With the TALWebRTC component, you can easily integrate video and audio chat into your applications, providing users with a more interactive and immersive experience! Learn more at Demos/ALLiveVideoChat

Confetti Falling Animation

ALConfetti is a lightweight and highly efficient Delphi library designed to create visually appealing, customizable confetti falling animations. Built for performance and flexibility, it allows developers to easily adjust parameters such as speed, size, and color, ensuring seamless integration into any project. Whether it's for celebrations, notifications, or dynamic visual effects, ALConfetti delivers a smooth, high-performance animation experience. Learn more at Demos/ALConfetti

confetti


AndroidMerger: Integrate AAR SDK in FMX Android App

An Android library, also known as an Android Archive (AAR), contains everything needed to build an app, including source files, resource files, and the manifest. Unlike JARs, AARs can include resource files in addition to compiled bytecode.

Integrating an AAR into a Delphi project can be a long and complex process, involving extracting resources, manually adding them to Delphi deployment files, compiling the R.java class, checking dependencies, and more.

With AndroidMerger, this entire process is automated in a single command line. In short, AndroidMerger will:

  • Use Gradle or an internal implementation to list all dependencies.
  • Download libraries and dependencies from local or central Maven repositories.
  • Merge the resources of all AARs into a single directory.
  • Combine the AndroidManifest files of all AARs into AndroidManifest.template.xml.
  • Merge google-services.json into the project's resources.
  • Create the R.jar with all resource IDs using aapt or aapt2.
  • Update the project file (.dproj) to include all resources.
  • Generate the Delphi native bridge file from the Java libraries.

Learn more at Tools/AndroidMerger

DeployMan / DeployProjNormalizer / DProjNormalizer

  • DeployMan simplifies the deployment of files and folders for iOS and Android apps, making it ideal for managing large files like third-party SDKs. Learn more at Tools/DeployMan.

  • DeployProjNormalizer enables the creation of a new deployproj file from scratch using the dproj as a reference, normalizing it by ordering nodes to facilitate comparison across different revisions with diff tools. Learn more at Tools/DeployProjNormalizer.

  • DProjNormalizer focuses on ordering nodes in a DProj file, ensuring consistency across commits and simplifying the comparison of changes. Learn more at Tools/DProjNormalizer.


Interpolated Animation

The TALAnimation component is a refined version of Delphi's foundational TAnimation object, specifically optimized for mobile platforms. Instead of relying on the traditional Timer mechanism, this component adopts platform-specific technologies, delivering a significantly improved animation experience for mobile users.

  • On Android, animations are seamlessly integrated with the Choreographer, ensuring perfect synchronization with the device’s refresh rate.

  • On iOS, the precision of DisplayLink is utilized, resulting in smooth and optimized animation rendering.

A key enhancement of TALAnimation is its support for custom interpolation algorithms, giving developers the flexibility to create unique and complex animation patterns, far beyond the traditional ease-in or ease-out sequences.

Interpolated Animation     Interpolated Animation

Learn more at Demos/ALAnimation

SpringForce Animation

SpringForce Animation

Inspired by Android's SpringForce, the TALSpringForceAnimation component brings the dynamics of physics-based animations to the Delphi platform. This component simulates the real-world behavior of objects influenced by spring mechanics, producing animations that stretch, bounce, and settle, mirroring the physical world.

Developers can fine-tune various physical properties of the spring, such as stiffness and damping ratio, allowing for a wide range of animation behaviors. This flexibility enables developers to create animations tailored to the specific nuances of different applications, offering a more realistic and engaging user experience. This version improves the flow and clarity of the description while keeping the markdown formatting

Learn more at Demos/ALAnimation



Scrolling Engine

Scrolling Engine

TALOverScroller and TALVelocityTracker are key components of the TALScrollEngine, enhancing user interface interactions. TALOverScroller manages scrolling and flinging with smooth deceleration when users scroll past a view's edge, while TALVelocityTracker measures touch velocity to determine gesture speed and direction. Together, they provide smooth animations and intuitive feedback within the scrolling engine.

Rather than reinventing the wheel, we based the TALScrollEngine on proven Android components, translating VelocityTracker and OverScroller from Java and C++ to Delphi. This ensures a high-quality, reliable scrolling experience for Delphi developers, using trusted, efficient technologies.

Learn more at Demos/ALFmxControls



Firebase Cloud Messaging

The Delphi implementation of the latest version of Firebase Cloud Messaging (FCM) using the HTTP V1 protocol enables you to send advanced push notifications, including rich media like images, to Android and iOS devices. This allows developers to deliver real-time alerts, updates, and user-specific notifications directly to mobile users, improving engagement and communication within their apps.

Learn more at Demos\ALNotificationService

GeoPositioning for Android/iOS

The TALGeoPositionSensor component is a Delphi component that provides access to location services on iOS and Android devices. It allows developers to retrieve the device's current location and receive updates as the location changes. The component supports various location providers, including GPS, cellular network triangulation, and Wi-Fi positioning.

In addition to accessing location services, TALGeoPositionSensor automates the process of requesting user permission to use location data on both iOS and Android. It also handles scenarios where users have previously denied location access. By using this component, developers can seamlessly integrate location-based functionality into their apps without needing to manage the underlying implementation details.

Learn more at Demos\ALGeoPositionSensor

Google OAuth 2.0 Access Token

Google APIs utilize the OAuth 2.0 protocol for authentication and authorization. The function ALGenerateGoogleOAuth2AccessToken allows you to easily generate an OAuth 2.0 access token, which can be used to securely access Google services and APIs within your Delphi applications.

Learn more at Source/Alcinoe.Cipher.pas

Android/iOS VKontakte/Facebook SDK login

The VKontakte/Facebook SDK for Android and iOS allows users to sign into your app using their VKontakte or Facebook credentials. Once logged in, users can grant permissions to your app, enabling you to retrieve information or perform actions on VKontakte/Facebook on their behalf.

Learn more at Demos\ALFacebookLogin

Photo Editor Filters for Android/iOS

With TALColorAdjustEffect, you can effortlessly apply stunning photo filters to enhance your images with just a single tap. Transform your photos into beautiful and expressive works of art in minutes!

Learn more at Demos\ALFmxFilterEffects

   


Json Parser

TALJSONDocument is a Delphi parser and writer for both JSON and BSON data formats. It supports both DOM and SAX parsers (although a more appropriate name for SAX could be SAJ—Simple API for JSON—rather than Simple API for XML, the well-known SAX terminology is retained).

In addition to its JSON capabilities, TALJSONDocument also supports the BSON format, using a syntax similar to TALXMLDocument/TXMLDocument. It can further export JSON/BSON data to TALStringList, making it a flexible tool for data parsing and manipulation in Delphi applications.

Example :

    {
      _id: 1, // comments
      name: { first: "John", last: "Backus" },
      birth: new Date('1999-10-21T21:04:54.234Z'),
      contribs: [ "Fortran", "ALGOL", "Backus-Naur Form", "FP" ],
      awards: [
                { award: "National Medal of Science",
                  year: 1975,
                  by: "National Science Foundation" },
                { award: "Turing Award",
                  year: 1977,
                  by: "ACM" }
              ],
      spouse: "",
      address: {},
      phones: []
    }

To access the document nodes :

    MyJsonDoc.GetChildNodeValueInt32('_id', 0{default if node not exists});
    MyJsonDoc.GetChildNodeValueText(['name','first'], ''{default if node not exists});
    MyJsonDoc.GetChildNodeValueDateTime('birth', Now{default if node not exists});

Learn more at Source/Alcinoe.JSONDoc.pas

ImageMagick Wrapper for Delphi

Use ImageMagick® to create, edit, compose, or convert bitmap images. It supports over 200 image formats, including PNG, JPEG, GIF, HEIC, TIFF, DPX, EXR, WebP, Postscript, PDF, and SVG.

With ImageMagick, you can resize, flip, mirror, rotate, distort, shear, and transform images. Additionally, it allows for color adjustments, the application of various special effects, and the drawing of text, lines, polygons, ellipses, and Bézier curves. This powerful tool enables a wide range of image manipulations within Delphi projects.

Example :

    //Create the ImageMagick Library
    ALCreateImageMagickLibrary({alcinoe} + '\Libraries\dll\imagemagick\win32\imagemagick', min(2, System.CPUCount){aThreadLimit});
    try
    
      //create the wand pointer
      var LWand := ALImageMagickLib.NewMagickWand;
      try
    
        //load the image
        if ALImageMagickLib.MagickReadImage(LWand, pansiChar(aInputFilename)) <> MagickTrue then RaiseLastMagickWandError(LWand);
        
        //Set the compression quality
        if ALImageMagickLib.MagickSetImageCompressionQuality(LWand,80) <> MagickTrue then RaiseLastMagickWandError(LWand);
    
        //autorate the image
        if ALImageMagickLib.MagickAutoOrientImage(LWand) <> MagickTrue then RaiseLastMagickWandError(LWand);
    
        //Resize the image using the Lanczos filter
        if ALImageMagickLib.MagickResizeImage(LWand, 640, 480, LanczosFilter) <> MagickTrue then RaiseLastMagickWandError(LWand);
           
        //save the image
        ALImageMagickLib.MagickWriteImage(LWand, pansiChar(aOutputFilename));
    
      finally
        ALImageMagickLib.DestroyMagickWand(LWand);
      end;
  
    finally
      ALFreeImageMagickLibrary;
    end;

Learn more at Source/Alcinoe.ImageMagick.pas

Streamlining Object Initialization with TALInit

In the constant evolution of software development, we often find ourselves seeking ways to reduce boilerplate code and enhance the maintainability of our projects. One such instance where boilerplate can become cumbersome is in the initialization of class fields. The traditional method involves explicitly setting each field's value in the constructor, which can be tedious, especially for classes with numerous fields. Enter TALInit—a feature that allows automatic initialization of object fields based on their attributes.

The Traditional Way

In the typical approach, developers manually initialize object fields in the constructor. Take the following class as an example:

    TAutoInitObject = class(TObject)
    public
      CharValue: Char;
      ChildObject: TChildObject;
    public
      constructor Create; virtual;
      destructor Destroy; override;
    End;

Here, each field is initialized in the Create constructor:

  constructor TAutoInitObject.create(const aOwner: Tform1; const AAutoInit: Boolean);
  begin
    CharValue := 'A';
    ChildObject := TChildObject.create;
    ChildObject.Name := 'AnObject';
    ChildObject.Value := 12.2;
  end;

  destructor TAutoInitObject.Destroy;
  begin
    ALFreeandNil(ChildObject);
    inherited;
  end;

While this method offers precise control, it can become tedious for large classes with numerous fields.

The TALInit Way

Imagine having a mechanism that not only automates this but is also as fast as the traditional way - yes, you read that right. TALInit achieves this remarkable feat.

  TAutoInitObject = class(TObject)
  public
    [TALInit('A')]
    CharValue: Char;
    [TALInit('Name:AnObject;Value:12.2')]
    ChildObject: TChildObject;
  End;

By using custom attributes, every field within the object can be automatically initialized based on its corresponding attribute. This eliminates the need for manually setting each field within the constructor. The above snippet showcases just how concise and readable object field initialization can become with TALInit.

Performance - A Game Changer:

One of the strongest advantages of using TALInit is its performance. When introducing automation, a natural concern is the overhead that might come with it. However, TALInit is designed to be as efficient as the traditional way of initializing fields. This means developers can enjoy the convenience without having to worry about any hidden costs in execution time.

Learn more at Alcinoe/tree/master/Demos/ALRTTI

MongoDb client

This is a Delphi driver with connection pooling for accessing a MongoDB server. Connection pooling refers to a cache of database connections that are maintained for reuse, reducing the need to establish a new connection for each request. Once a connection is created, it is placed in the pool and can be reused for future database requests.

If all connections in the pool are in use, a new connection is created and added to the pool. This approach reduces the time required to establish connections, enhancing performance and efficiency when interacting with the MongoDB database.

Learn more at Source/Alcinoe.MongoDB.Client.pas

WebSocket client

The WebSocket client for Delphi is built on top of WinHTTP and provides a communication protocol for two-way, interactive communication sessions between a user's browser and a server. This enables sending messages to a server and receiving event-driven responses without the need for constant polling.

With WebSocket, real-time communication is streamlined, making it ideal for applications that require low-latency, continuous data exchange between the client and server.

Learn more at Demos\ALWinHTTPWebSocketClient

Fast TStringList

TALStringList functions similarly to Delphi's TStringList, but with significant performance improvements. When the list is sorted, it uses a quicksort algorithm to search for name=value pairs, enabling much faster lookups.

Additionally, TALStringList uses a locale-independent sorting algorithm based on the 8-bit ordinal value of each character, rather than Delphi's AnsiCompareText and AnsiCompareStr. This results in sorting speeds up to 10 times faster than Delphi's TStringList.

Unlike TStringList, TALStringList is not Unicode-based but is a fully Ansi string list, optimized for performance.

You can start exploring this feature with the demo located at Demos\ALSortedListBenchmark

PHP runner

ALPHPRunnerEngine is a simple yet powerful component that allows you to seamlessly use PHP (any version) as a scripting language within Delphi applications. With ALPHPRunnerEngine, you can execute PHP scripts directly in your Delphi program without the need for a web server.

This component leverages the CGI/FastCGI interface (using php-cgi.exe) to communicate with the PHP engine, making it easy to integrate PHP functionality into Delphi-based projects.

Learn more at Demos\ALPhpRunner

Memcached Client

What is Memcached? Memcached is a free, open-source, high-performance, distributed memory object caching system. It is generic in nature but is primarily used to speed up dynamic web applications by reducing database load. By caching frequently accessed data in memory, Memcached helps improve the performance and scalability of applications.

Learn more at Source/Alcinoe.MemCached.Client.pas

GSM Component

The TAlGSMComm component enables SMS text messaging using the text-mode interface defined in the GSM Technical Specification 07.05. This component allows for easy integration of SMS functionality into your applications, adhering to the standard protocols used in GSM networks.

Learn more at Source/Alcinoe.GSMComm.pas

SQLite3 Client

The SQLite3 Client for Delphi allows you to query an SQLite3 database and retrieve the results in multiple formats, including XML, JSON, and BSON. This flexibility makes it ideal for applications that require data exchange in different formats, enabling smooth integration with various systems and APIs.

Learn more at Source/Alcinoe.Sqlite3.Client.pas

And Much More

  • CGI Runner
  • Http Client (WinInet/WinHTTP)
  • MySQL Client
  • NNTP Client
  • POP3 Client
  • SMTP Client
  • Xml Parser
  • Etc ...


DELPHI D2009+ (UNICODE)

There's no doubt that Unicode was necessary for a product like Delphi. However, the approach Embarcadero chose for its implementation has raised some concerns. Instead of adopting UTF-8 through 8-bit strings, they opted to migrate from 8-bit strings to 16-bit strings (UTF-16). This decision made migrating Delphi applications prior to D2009 challenging, especially for those that relied on the assumption that strings were 8-bit.

For more insights into why UTF-16 can be problematic, here's an excellent article: utf8everywhere.org.

Starting with D2009, AnsiString now has a code page, and some transliteration occurs when assigning an AnsiString with one code page to another AnsiString with a different code page (e.g., OldCodePage => UTF-16 => NewCodePage). To prevent unwanted transliterations, it's crucial to set the project's code page to the desired one (e.g., 65001 for UTF-8) and call SetMultiByteConversionCodePage(CP_UTF8) at the beginning of the program.

Additionally, avoid mixing different string types (e.g., UTF8String and AnsiString) even if they share the same code page. The Delphi compiler doesn't recognize this at compile time and will still perform unnecessary transliterations (e.g., MyAnsiStringUTF8 := MyUTF8String results in UTF-8 => UTF-16 => UTF-8).

To minimize these issues, it's best to use AnsiString exclusively in your code, even when handling UTF-8 content. Always ensure that AnsiString is paired with SetMultiByteConversionCodePage(CP_UTF8) to prevent undesired conversions.