Artykuł techniczny

Rysowanie na płótnie HotPDF w Delphi: Ścieżki wektorowe i kolory

HotPDF rysuje grafikę wektorową, budując ścieżkę na bieżącej stronie, a następnie prosząc o jej namalowanie. Nie ma po drodze etapu bitmapy. Linia narysowana za pomocą MoveTo i LineTo kończy się jako operatory ścieżki PDF w strumieniu treści, dzięki czemu pozostaje prawdziwym wektorem: wyraźnym przy powiększeniu 50%, wyraźnym przy powiększeniu 1600% i stanowiącym ułamek rozmiaru, jaki kosztowałaby wersja rastrowa. W przypadku diagramów, linii tabeli, osi wykresów i dekoracji formularzy, jest to dokładnie to, czego chcesz, a API stojące za tym jest wystarczająco małe, aby nauczyć się go w jedno posiedzenie

Cała powierzchnia rysowania znajduje się na obiekcie THotPDF.CurrentPage. Pomiędzy BeginDoc a EndDoc ustawiasz kolor i grubość linii na tym obiekcie strony, układasz geometrię i wywołujesz operator malowania, aby ją zatwierdzić. Cztery najczęściej używane prymitywy to MoveTo i LineTo dla dowolnych ścieżek, Rectangle dla pudełek, Circle dla okręgów i dwa operatory malowania: Stroke i Fill

Układ współrzędnych zaczyna się w lewym dolnym rogu

Jest to jedyna rzecz, na której potykają się wszyscy przechodzący z VCL. Płótno TCanvas, którym malujesz kontrolki, umieszcza początek układu w lewym górnym rogu z Y rosnącym w dół. PDF robi odwrotnie. HotPDF mierzy od lewego dolnego rogu strony w punktach (1/72 cala), przy czym wartość Y rośnie w miarę poruszania się w górę. Punkt na wysokości Y := 720 znajduje się blisko góry amerykańskiej strony Letter, która ma 792 punkty wysokości, a Y := 50 blisko dołu. Jeśli twój pierwszy rysunek wychodzi odwrócony w pionie, to właśnie dlatego: kod przeniesiony z grafiki ekranowej zakłada niewłaściwy kierunek i wychodzi poza dolną krawędź

Ta sama konwencja dotyczy funkcji TextOut, więc tekst i kształty współdzielą jeden model mentalny, gdy już go przyswoisz. Zaplanuj układ, decydując, gdzie znajduje się dół każdego elementu, a nie góra, a reszta ułoży się sama

Ścieżki: MoveTo, LineTo, Stroke

Ścieżka obrysowana to uniesiony długopis, przyłożony i przeciągnięty. MoveTo podnosi pióro i ustala punkt początkowy bez zaznaczania czegokolwiek. Każde użycie LineTo rozszerza bieżącą ścieżkę do nowego punktu. Na stronie nic nie pojawia się, dopóki nie wywołasz metody Stroke, która rysuje zgromadzoną ścieżkę przy użyciu bieżącego koloru i grubości linii, a następnie czyści ścieżkę, tak że kolejne użycie MoveTo zaczyna od nowa

var
  Pdf: THotPDF;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := 'DrawPaths.pdf';
    Pdf.BeginDoc;

    // Line width is in points and applies until you change it.
    Pdf.CurrentPage.SetLineWidth(1.5);
    Pdf.CurrentPage.SetRGBStrokeColor(clBlack);

    // A horizontal rule near the top of the page (Y measured from bottom).
    Pdf.CurrentPage.MoveTo(72, 720);
    Pdf.CurrentPage.LineTo(523, 720);
    Pdf.CurrentPage.Stroke;          // commit the path; nothing drew before this

    // A thicker connected polyline: three segments in one path.
    Pdf.CurrentPage.SetLineWidth(3);
    Pdf.CurrentPage.SetRGBStrokeColor(RGB(30, 90, 200));
    Pdf.CurrentPage.MoveTo(72, 640);
    Pdf.CurrentPage.LineTo(172, 690);
    Pdf.CurrentPage.LineTo(272, 620);
    Pdf.CurrentPage.LineTo(372, 680);
    Pdf.CurrentPage.Stroke;

    Pdf.EndDoc;
  finally
    Pdf.Free;
  end;
end;

Dwa szczegóły pozwalają zaoszczędzić prawdziwy czas debugowania. Grubość linii jest stanem, a nie argumentem: metoda SetLineWidth ustala go raz i każde kolejne wywołanie Stroke korzysta z tej wartości, dopóki znowu jej nie zmienisz. Dlatego łamana powyżej jest grubsza niż linia zasady. Ścieżka również resetuje się po każdym użyciu Stroke, więc zapomniany Stroke oznacza, że skrupulatnie zaplanowana geometria w ogóle się nie wyrenderuje. Jeśli brakuje kształtu na wyjściu, wywołanie malowania to pierwsze miejsce, w którym należy szukać przyczyny

Współrzędne są punktami, a punkty są ułamkowe. Metody MoveTo i LineTo przyjmują wartości typu Single, więc bardzo cienka linia na poziomie 0.5 punktu lub pozycja 72.25 są legalne i znaczące, nie są zaokrąglane do najbliższej całkowitej jednostki. Ta precyzja ma znaczenie w dwóch przeciwległych kierunkach. Grubość linii poniżej ok. 0.5 może renderować jako zależna od urządzenia najcieńsza możliwa linia, która znika z ekranu i powraca podczas druku, stąd dobrze widoczna linia wymaga grubości celowo ustawionej, a nie domyślnej. Z drugiej strony przyciąganie linii tabeli i siatek do współrzędnych pełnych punktów pozwala zachować wrażenie równości na gęstej siatce, podczas gdy sąsiednie linie mogłyby ulegać niejednolitym zaokrągleniom. Wpierw zdecyduj o rozmiarze punktowym przerw w siatce, a reszta układu go odziedziczy

Kształty wypełnione i kolory

Kształty zamknięte mogą być wypełnione zamiast bycia jedynie narysowanymi w formie konturu. Funkcja Rectangle przyjmuje pozycję oraz rozmiar, funkcja Circle wymaga środka i promienia, i obydwa te operatory mogą być ostatecznie zaaplikowane przez użycie Fill, co pomaluje wnętrze ustawionym obecnie kolorem wypełnienia, bądź z użyciem Stroke celem uzyskania tylko konturu. Kolor wypełnienia i kolor obrysu są osobnymi fragmentami stanu, ustalanymi przez użycie SetRGBFillColor oraz SetRGBStrokeColor, z których obydwa przyjmują wartość pojedynczą TColor. Oznacza to możliwość powtórnego korzystania z wbudowanych stałych kolorystycznych w środowisku Delphi wraz z wbudowaną klasą pomocniczą RGB całkowicie bez pośredniości

// Rectangle(X, Y, Width, Height): X and Y are the lower-left corner.
Pdf.CurrentPage.SetRGBFillColor(RGB(220, 60, 60));
Pdf.CurrentPage.Rectangle(72, 500, 160, 90);
Pdf.CurrentPage.Fill;

// Circle(X, Y, Radius): X and Y are the center.
Pdf.CurrentPage.SetRGBFillColor(clNavy);
Pdf.CurrentPage.Circle(420, 545, 45);
Pdf.CurrentPage.Fill;

// Outline only: set a stroke color and a width, then Stroke.
Pdf.CurrentPage.SetLineWidth(2);
Pdf.CurrentPage.SetRGBStrokeColor(clBlack);
Pdf.CurrentPage.Rectangle(72, 400, 160, 60);
Pdf.CurrentPage.Stroke;

Zwróć uwagę na format argumentów metody Rectangle. Jest to pozycja i wymiary, X, Y, Szerokość, Wysokość, a nie dwa przeciwległe narożniki. Wykorzystywany w Delphi obiekt TCanvas.Rectangle przyjmuje (Left, Top, Right, Bottom), przez co pamięć mięśniowa podpowie podanie do HotPDF przeciwległego rogu w miejscu, gdzie program wymaga podania szerokości i wysokości, a narysowane okno otrzyma niewłaściwy rozmiar. Para (X, Y) to lewy dolny narożnik, zgodny z początkiem układu dla całej strony. W przypadku koła (X, Y) jest jego środkiem, a trzecim argumentem jest promień w punktach

Pojedyncza decyzja dotycząca palety barw pomyłkowo wykonana we wcześniej utworzonym przykładzie

Starsza wersja niniejszego artykułu dobierała dla każdego z kształtów barwę za pomocą instrukcji Random($FFFFFF). Pozornie jawi się ono intrygującym, aczkolwiek bywa ono nieprawidłowym założeniem względem automatycznie generowanych dokumentów w ogóle. Plik w formacie PDF utworzony od podstaw przez kod programu częstokroć poddaje się późniejszym weryfikacjom, natomiast zastosowanie wygenerowanych losowo odcieni wyklucza bezpośrednie porównanie przy różnych iteracjach operacji: proces sprawdzający bit po bicie oparty o już wcześniej zakwalifikowany sprawdzany dokument odrzuci go przy absolutnie każdym wywołaniu dla niezbyt racjonalnej argumentacji. Zalecane jest wskazywanie barw w postaci nie budzącej wątpliwości. W razie zapotrzebowania na odmienność barw przy szeregu podobnych obiektów, wywiedź ich wybór na bazie tablicy palet, z której korzysta program przy wprowadzanych danych wejściowych, aby w konsekwencji otrzymany ostatecznie wejściowy argument był ten sam. Zachowanie jednolitych wartości i wyeliminowanie pierwiastków losowości okazuje się znacznie bardziej priorytetowym przedsięwzięciem ponad samą innowacyjność po skierowaniu przez strumienie uwolnienia (tzw. release)

Komponowanie prymitywów na nowo: oznacznik "callout"

Pojedynczy kształt wydaje się banalny w swej odizolowanej formie; wyższą formę ukazuje jako konglomeracja elementu dla tworzonego poświadczenia czy raportu wymagającego takiej grafiki z autentyczności. Wzmiankowany element powiadamiający to oznaczający określoną rycinę w celach wyjaśniających go kwadrat o krawędziach połączonych w wyrysowaną w oznaczanym obszarze ramką, która implementuje każdy objęty dotychczas komponent: z włączającym wypełnionym zakryciem i uwydatnionymi obrysami, oznaczającym połączeniem z rzutowanym szlakiem z ukierunkowaniem i punktem zaczepienia o wyznaczonym u złączonego kształtem tekstu rozmieszczonego według w tych samych lewych dolnych koordynatach pospołu z formą. Wykorzystywana klasa zwana operatywnie FillAndStroke staje się nad wyraz korzystną tu z perspektywy wyrysowania naraz konturu okalającego z nałożonym wypełniającym malowaniem poprzez proces zatwierdzania bez koniecznego dla uformowania figury dwa z rzędu podwojonego wykonywania w systemie polecenia rysowania

var
  Pdf: THotPDF;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := 'Callout.pdf';
    Pdf.BeginDoc;

    // 1. The box: pale fill plus a visible border, one path, one commit.
    //    Rectangle is lower-left corner plus size, Y measured from the bottom
    Pdf.CurrentPage.SetRGBFillColor(RGB(255, 244, 214));   // pale amber panel
    Pdf.CurrentPage.SetRGBStrokeColor(RGB(180, 130, 40));  // darker rim
    Pdf.CurrentPage.SetLineWidth(1);
    Pdf.CurrentPage.Rectangle(90, 600, 240, 70);
    Pdf.CurrentPage.FillAndStroke;

    // 2. The pointer: one stroked segment from the box edge down
    //    toward the thing being annotated
    Pdf.CurrentPage.SetLineWidth(1.5);
    Pdf.CurrentPage.MoveTo(90, 615);        // left edge of the box
    Pdf.CurrentPage.LineTo(66, 546);
    Pdf.CurrentPage.Stroke;

    // 3. A filled dot anchors the pointer at its target
    Pdf.CurrentPage.SetRGBFillColor(RGB(180, 130, 40));
    Pdf.CurrentPage.Circle(64, 542, 3);
    Pdf.CurrentPage.Fill;

    // 4. The label, positioned relative to the box's lower-left corner.
    //    Text and shapes share one coordinate system, so the offsets
    //    are plain arithmetic against (90, 600)
    Pdf.CurrentPage.SetFont('Arial', [fsBold], 10);
    Pdf.CurrentPage.TextOut(102, 645, 0, 'Check this total');
    Pdf.CurrentPage.SetFont('Arial', [], 9);
    Pdf.CurrentPage.TextOut(102, 628, 0, 'The rounding rule changed in the');
    Pdf.CurrentPage.TextOut(102, 616, 0, 'June release; verify against v2.1');

    Pdf.EndDoc;
  finally
    Pdf.Free;
  end;
end;

Zwróć uwagę na niewielką ilość użytego tutaj do zarządzania stanem procesu wykonawczego połączonego ze sobą kodu. Przed wykonaniem danego kształtu określamy dla niego tuż obok poszczególnych komponentów formujących wyznaczoną specyfikację koloru malowania, z zaznaczeniem konturowania i doborem w wytyczeniu proporcji skali wymiaru przez określenie go bezpośrednio przez każdą poszczególną linię by w zablokowaniu jego właściwości po obiekcie stał się on swoistym wolnym z możliwością zmiany położenia kodem bez wpływania na proces dla elementu kolejnego ukrytego przez formę w ukrytej zmianie atrybutów. Wprowadź modyfikacje, aby stał się samodzielną zdeklarowaną ze spisanym zapotrzebowaniem jako oddzielnie uformowanym z zastosowanym wyznaczanym ujęciem procedur opartą w strukturze na czterdziestu rzędach o mniejszych kosztach odrębnie przydatnej specyfikacji dla wykresów przy notyfikacji z możliwością dodawania tekstów do rysunków

Zastosowanie i korzyści grafiki wektorowej, czyli po co to wykonujemy, a także argumentacje i przesłanki przeczące by pójść z tym oznaczonym sposobem podjętego kierunku z wykonanymi rozpisaniami i projektowaniami

Sposób oznaczający w implementacji z tworzonym z wektorowej rozwijanej procedury formowania z operacjami geometrycznymi ukierunkowanego rysowania oznaczającego szczytowy rezultat: ustrukturyzowana obrysowanymi ramami siatka przy zestawieniu barowym dla raportowego oznaczenia faktury rachunkowej i rzędów tworzących z podanych danych z nakładkami, ze skomponowaną zawartością znakową lub podaną liniową w logotypowym rzucie wizualizującą oprawą. Powiązania takie w wymierzonych skalach formują wyraźną formę dla obrazu wolną z utraty ze zredukowanej wartości ostrości bez nabrania proporcjonalnych znaczniejszych wzrostów obciążeniowych na formacie dla pliku z utworzoną geometryczną postawioną rzutowaną informacją o wirtualnych wyliczeniach mniejszych od tysięcy pojedynczo przypisywanych w wymiarowanej osnowie pikseli dla strukturalnego układu obrazka przez zawarty wewnątrz wyliczany przez punkty układ ze wstawionymi wartościami zamiast punktów wizualizacji piksela. Powiedzmy to o innej możliwości szczerze dla porównania. Jeśli w ramach podanych posiadanych we wgraniu wizualizowanych informacji do prezentowania do wglądu stanowią w formacie ryciny czy też ze zrzuconym obrazem ekranowym operatywne wkomponowanie na tło formantu jako zastosowanie rozkładu dodającego wykorzystującego AddImage z włączonymi procesami po wydanym przez aplikację wywołaniem procedury z funkcją ShowImage w zestawieniu nie da to przyłożonych rezultatów dla wektorowo kreowanych procesów na operacjach w zastosowanych przez ramy. Linie proste poprowadzonych połączeń po włączeniu rzutu okręgami u opisywanych zastosowań stanowiących mniejszość lub wykraczających nad formującym formę o wielokroć powszechnie stosowanego od lat rozwiązania stanowią tu o oznaczaniu przez dopuszczony wyodrębniony do określania ukształtowania i wizualizacji w używaniu krzywych rzutowych po wprowadzonym wstawieniu obok stosowanego szlakowo po przerwanych lub opcjach wizualizacji form przejrzystości, będąc u na posadowione w osadzeniach stronnicowych obiektowych wywołaniach

Szkice po krawędziach krzywizny wraz z przerywanymi wytyczeniami oraz wpół przejrzystymi elementami objęte we wnikliwym oszacowanym zarysie problematyki

Tworzenie zarysu dowolnych kształtów wywiedzionych w procesie rzutowania z wdrożonej w oparciu przez szlak dla krzywizny maszyny odbywa się i polega o rozwinięcia poprzez powiązaną relację. Instrukcja w zapisie z przypisaną funkcją CurveToC(X1, Y1, X2, Y2, X3, Y3) do rzutowanego wpisanego zarysu bieżącej nakierowanej na rzut dla wskazanego celu opcji ze włączeniem wyrysowanego wdrożenia do kształtnego wyciągnięcia odcinków przez parametry do ustalonego o ukierunkowaniu pod (X3, Y3) dążąc po dopasowywaniu ugięć odnośnie przypisanych dwóm nakazom przez ukształtowaną modyfikacją wycinka, dla którego w skróconych podaniach CurveToV i CurveToY wprowadzono dla możliwości zastąpienia pokrycia z zakończeniem w przypisanych obramowaniach. Wdrożona na formatkach ścieżka umożliwia swobodne włączanie wywołań w trybie rzutowanych po liniach LineTo w złączeniu od uformowanych po wytyczeniach poprzez stosowany przypis CurveToC wyrywkowo oznaczony u ułożeniowych od wykresu w wariancie łączenia wywołanej komendzie bez nakazanego pojedynczego zatwierdzenia po wywoływanym w formowaniu w jednym Stroke dla pojedynczej operacji lub dopuszcza wpisy o zatwierdzeniach by za pomocą w polecenia z funkcją z wypełnieniem w używanym Fill rzutowanej w wirtualnych punktowych narożnikach zaokrąglonej pod budowanych sprofilowanych szlakowo rozpisanych układach

Pojedyncza decyzja ze stanu formatowania konturu od używanych kreskowań u przypisanego z grubości po ustawieniu po wpisie jest wiążącą jako ta dla rysowanej formacji o wykreślanych wartościach pod postacią sztywno rzutowanych pociągniętych pasm. W SetDash([3, 3], 0) przywoływany po podanych wpisach pod formację u objętych w zmianę z zaznaczonego przy procesowym rysie kreskowym operatywnym procesem zmiany każdego konturu kolejnego zastosowanego oznaczającego przy formatowanym przez ułożenie 3x aktywowanych, wpisując rzutowanych wygaszonych trzech we włączanym dla przypisanego po wyliczonych wymiarach zapisu cyklu punktów przez obok przerywanego pod ciągłe łączenia z wartości; pod NoDash wpis następuje w ustawieniu o przerwaniu u złączeniu konturów. Wywołaj ze stanu formatowania u tworzonych rozkładanych za rysunkiem po konturach po określonych by formacjach powróciły by wpisać odnowione przywracania stanu przed każdym powtarzanym po ujęciu rozkładów po operacyjnym wykonaniu linii prostych tak przez zapis uniknie rozciągnięć przypisywanych rzutowo bez ograniczeń do rzutowanego opcjonalnie od na każdym z etapów dla tworzenia

Zastosowane przypisy przez opcję oznaczanej ujętym przejściu graficznym oznaczanego do transparentnych wpisów dla przezroczystych obrysów jako stany formowane wywołaniami a niedotyczących ustawianym dopisywanym z parametrem u koloru, po zapisanej alfie rzutowanej u dokumentacji słownikowej u PDF we właściwości we wbudowanej pod zmienionych układach. Przypisz i ustaw operację nakazu poprzez format dokumentacji przy wpisie operacji by uwzględniło wprowadzone RegisterExtGState, stosujące wprowadzone u pozycjonowanych wyznaczających i wypełnianych z przedziałem od zero u jedynki wraz z narzuconym przypisanym mianem wyciągającym dla CurrentPage.SetGraphicsState; po opcjach rzutów konturów z włączonym przez polecenie malowania obrysach dla wskazanej wartości przejrzystości. Procedura okazuje się być obciążona większym formalizmem niż u opcjonalnie stosowanych w zmianach kolorystyki, więc w razie koniecznego naniesienia elementu zakrywającego napisy przy zapewnieniu opcji oznaczającej i podświetlenia opłaca się bez uniemożliwiania jej odczytywania wykonać zapis dla włączenia

Zachowana tu u obrysowanych przypisów warta zanotowania operatywna w praktyce jest rzutowana przy testowanych po weryfikacji. Opcja uruchamiana po generowanej u układu formacjach często ukazuje poprawność a w innych błędnie w systemie klienckich ustawień wywołujących obarczonych zmianą po podmienianym przy znakach po na włączonych opcjach u weryfikowanego formatowania o ukształtowanych pod obiekty na rzutowanym braku formatowanych w wielkości pod formatów wprowadzonych na stronę przy włączanym po rzucie u błędnego ustawienia za włączanym po błędnym ujęciach z góry dopisanego. Podnieś opcje użycia poprzez wymierzonych wizualnie powiększonych wyjściowo wywoływanych skal i dokonaj testowania pod powiększonymi wprowadzonymi za czysto obrysowanymi brzegami u użycia układów marginesów u testowanego obiektu tak wpisanego wywołaniem. Poprzez formaty w użyciu od determinujących wartości testowania kolorów pod wyjściowego automatyzowania na sprawdzaniu względem pliku pod format PDF odchodzi od ujętych i sprawdzanych poprzez rzucanych wyjściowo badanych wyrokiem na włączonym oko w układach dopisanych przy uruchamianych po teście testowanych dla poprawności pliku rzutowych o użyciowych opcji wizualizowania

Opisane tutaj używane z MoveTo, LineTo, Stroke, Fill oraz kolorów zaliczają się i pochodzą w formie jako części u użytego po Komponentu HotPDF z opcjami formatowanymi dla programów pod Delphi oraz C++Builder