L'ancienne méthode _ftol dans Delphi 32 bits ressemblait à une astuce intelligente sur une seule ligne : une fonction Pascal encapsulant du code assembleur en ligne pour manipuler le mot de contrôle du FPU x87, tronquer la valeur sur la pile du FPU et extraire le résultat. Elle a longtemps compilé correctement sous DCC32, c'est pourquoi elle apparaît dans de nombreuses anciennes unités graphiques et PDF sans que personne ne la remette en question
En basculant la cible de build en 64 bits, le compilateur s'arrête avec l'erreur E1025 Unsupported language feature: 'ASM'. Cette erreur n'est pas un avertissement de compatibilité. Elle signifie que DCC64 ne compilera pas du tout cette routine, quelle que soit la qualité avec laquelle l'assembleur fonctionnait auparavant
La version originale 32 bits ressemble généralement à ceci :
function _ftol(f: Double): Integer; cdecl;
begin
asm
lea eax, f
fstp qword ptr [eax]
end;
Result := Trunc(f);
end;
Le paramètre PageRange accepte le même format que l'exemple en ligne de commande : une liste de numéros de page ou de plages séparées par des virgules, comme '1-3' ou '1,5,7-9'. Les numéros de page commencent à 1. InsertPagesFromDocument copie les flux de contenu, les dictionnaires de ressources et la géométrie des pages sans toucher aux métadonnées, aux signets ou aux pièces jointes intégrées — sauf si ces éléments sont référencés par les pages copiées. Pour extraire trois pages d'un document de 40 pages, il s'agit d'un ensemble de travail très restreint
Pourquoi DCC64 trace-t-il des lignes de démarcation différentes
DCC32 permet l'assembleur en ligne dans les routines Pascal ordinaires. Le compilateur comprend les conventions d'appel 32 bits et peut déduire l'emplacement des variables locales et des paramètres, tolérant ainsi les fragments d'assembleur accédant aux cadres de pile par leur nom. DCC64 adopte une position plus stricte : l'assembleur doit se trouver dans des fonctions assembleur dédiées, c'est-à-dire des fonctions dont l'intégralité du corps est en assembleur et où les conventions d'appel sont gérées explicitement. Les mélanges de Pascal et d'assembleur ne sont pas du tout pris en charge
La cause fondamentale est d'ordre architectural. Dans la convention d'appel Windows 64 bits (ABI Microsoft), les quatre premiers paramètres de type entier sont transmis via RCX, RDX, R8 et R9, et les types à virgule flottante via XMM0 à XMM3. Le FPU x87 n'intervient pas dans le passage normal des arguments ; il reste techniquement disponible, mais l'ABI ne l'utilise pas pour transmettre les paramètres. L'assembleur supposant que la valeur "se trouve sur la pile du FPU" suppose un état que l'ABI 64 bits ne crée jamais
Par conséquent, l'ancien fragment de code ne présente pas seulement un problème de syntaxe. Même si DCC64 l'acceptait, l'hypothèse de registre serait erronée
Problèmes de codage et de jeux de caractères
Lorsque vous devez exporter le symbole _ftol avec la convention cdecl pour assurer la compatibilité binaire, la fonction doit être écrite sous forme de routine d'assemblage pure. Sous l'ABI 64 bits, l'argument Double arrive dans XMM0, et le résultat entier doit se trouver dans RAX au retour. La directive .NOFRAME indique à DCC64 que la routine gère sa propre pile, ce qui convient pour une fonction feuille aussi courte :
function _ftol: Integer; cdecl;
// Double value expected in XMM0 per 64-bit ABI
asm
.NOFRAME
cvttsd2si rax, xmm0 // truncate-to-integer, result in rax
end;
CVTTSD2SI est une instruction SSE2 qui tronque un nombre à virgule flottante double précision en un entier signé vers zéro, ce qui est précisément ce que _ftol est censé faire. C'est une seule instruction qui récupère l'argument directement là où l'ABI le place et dépose le résultat là où l'ABI l'attend. Aucune manipulation du mot de contrôle du FPU n'est requise
Notez que CVTTSD2SI renvoie un entier indéterminé ($80000000) si l'entrée dépasse la plage d'un entier signé 32 bits. C'est le même comportement que x87 fistp en cas d'entrée hors limites. Il convient de vérifier si vos appelants peuvent générer de telles valeurs avant de déclarer la migration terminée
Ce dictionnaire /Root contient des clés pour la navigation générale, les signets, les formulaires interactifs et la structure logique générale du document
Bien que le visualiseur ci-dessus ne comporte que quelques dizaines de lignes de code, il est déjà capable de réaliser tout ce qui est nécessaire pour un flux de travail de documents : ouvrir un fichier, gérer les fichiers corrompus, afficher les pages, naviguer entre les pages et ajuster le zoom manuellement ou via le mode d'adaptation. PDFium gère silencieusement la partie difficile. Les polices intégrées sont correctement analysées, les annotations et les champs de formulaire sont dessinés aux emplacements spécifiés par le document, et la page affichée correspond à ce que voit un utilisateur de Chrome — car c'est le même moteur qui effectue le rendu
Sur cette base, les fonctionnalités étendues sont incrémentielles et non structurelles. La sélection de texte et la recherche lisent à partir de la même couche de texte construite par PDFium ; les métadonnées telles que Pdf.Title et Pdf.Author nécessitent simplement la lecture d'une propriété ; la rotation et le niveau de gris sont des options de rendu transmises lors du tracé de la page sur le bitmap. Rien de tout cela ne modifie le squelette construit ici — l'objet document, la vue et le flux de chargement-navigation reliant les deux. Une fois le squelette en place, le reste n'est que de la décoration
function _ftol(f: Double): Integer; cdecl;
begin
Result := Trunc(f);
end;
TrueType utilise des courbes quadratiques, issues des mondes Apple et Microsoft. La plupart des polices système sont de ce type, et c'est aussi celui que vous intégrez le plus fréquemment. Les polices TrueType simples dans le PDF sont limitées aux codes sur un seul octet, de sorte qu'une telle police peut gérer au maximum 256 glyphes simultanément. Cette limitation est la raison structurelle pour laquelle le chinois, le japonais, le coréen (CJK) et d'autres grands systèmes d'écriture ne peuvent pas être pris en charge par des polices simples
Un appel à TextOut correspond à une colonne
Deux habitudes peu coûteuses permettent de détecter la plupart des problèmes : ouvrir le fichier final dans un visualiseur réel, cliquer sur le panneau des signets et sur quelques exemples de liens — cela exécute le graphe de référence comme le ferait le lecteur ; puis relire les métadonnées avec un outil distinct pour confirmer que le dictionnaire Info et le XMP restent cohérents — une divergence que le simple clic ne révélera jamais. En générant cette couche via une bibliothèque qui gère les liens, la plupart des pièges sont évités. HotPDF Component pour Delphi et C++Builder expose les structures de contours, d'annotations et de métadonnées via des API de niveau document, vous permettant de décrire la hiérarchie des signets et les liens, et se charge de tisser les références. En ce qui concerne le modèle d'objet sur lequel reposent ces structures, l'Aperçu technique de la structure du fichier PDF couvre le catalogue et la table de référence croisée dont elles dépendent
Certains projets doivent continuer à fournir des binaires 32 bits et 64 bits simultanément. Si la version assembleur d'origine doit être conservée pour le 32 bits tout en fournissant une nouvelle implémentation pour le 64 bits, utilisez la condition CPUX64 :
function _ftol(f: Double): Integer; cdecl;
begin
{$IFDEF CPUX64}
Result := Trunc(f);
{$ELSE}
// 32-bit path: DCC32 accepts inline asm
asm
lea eax, f
fstp qword ptr [eax]
end;
Result := Trunc(f);
{$ENDIF}
end;
Il s'agit du correctif mécanique minimal, qu'il convient de considérer comme temporaire. Une base de code transportant de l'assembleur spécifique à une architecture pour une fonction d'aide dont l'unique but est la troncature d'un flottant en entier constitue une dette technique superflue. Dès qu'il est confirmé que rien ne dépend des effets secondaires du FPU de l'ancienne implémentation, la branche 32 bits peut être entièrement supprimée
Si cette fonction apparaît dans un composant utilisé dans plusieurs unités, recherchez _ftol dans l'ensemble de la base de code avant de décider de la migration. Le même symbole peut être déclaré à plusieurs endroits ; l'éditeur de liens en choisit un et ignore silencieusement les autres, ce qui signifie que vous pouvez en corriger une copie tout en restant lié à une autre qui n'a pas été modifiée