Giter Club home page Giter Club logo

Comments (7)

galkahana avatar galkahana commented on July 24, 2024 1

PDFModifiedPage has GetCurrentResourcesDictionary that you can use for the same purpose as yo would use GetResourcesDictionary for a regular page.

The rest is the same.
here's an example for creating modified page, content context and writing the page.

from pdf-writer.

galkahana avatar galkahana commented on July 24, 2024

Hi :)

To write Oblique text all you have to do is find a font that's oblique. Same as you would for writing text in bold or italic. For example, here is a courier oblique version - https://fontsgeek.com/fonts/Courier-Oblique.

As for opacity, there are a few discussions in HummusJS (the JS version of this lib) and i think the most fitting is this one. While it discusses regular paths and not text, the solution is the same. Please have a look, it might be a shorter version of a longer explanation following here. If you want help with converting to C++ do let me know and i'll help.

The point is to apply a graphic static prior to drawing the said text (or path) that includes an opacity factor in it.
There are 3 steps to this:

  1. Creating the external graphic state dictionary
  2. Referring to this graphic state from the page or form that you want to draw the text in and giving it a name
  3. Applying the graphic state with the GS operator providing it the said name.
    Now you just draw the text with the usual text operators and the opacity defined in the graphic state will be applied.

here's an example of how to create the graphic state dict:

ObjectsContext *objCxt = pdfWriter->GetObjectsContext();
ObjectIDType gsId = objCxt->StartNewIndirectObject();
DictionaryContext* dict = objCxt->StartDictionary()
dict->WriteKey("type");
dict->WriteNameValue("ExtGState");
dict->WriteKey("ca");
objCxt->WriteNumber(0.5);
objCxt->EndLine();
objCxt->EndDictionary(dict);

gsId holds the object number for this dictionary. you will use it for the 2nd step.

here's an example of referring to the dictionary from a page resources dictionary:

string gstateName = myPage->GetResourcesDictionary().AddExtGStateMapping(gsId);

gstateName now holds the name of the extgstate that can be used within the page drawing context to apply the state, and allow drawing entities with 0.5 opacity.

For example:

PageContentContext* cxt = myPage->StartPageContentContext(page);
AbstractContentContext::TextOptions textOptions(
    pdfWriter.GetFontForFile("fonts/arial.ttf"),
    14,
    AbstractContentContext::eGray,
    0);
cxt->q();
cxt->gs(gstateName);
cxt->WriteText(75,805,"Yolo",textOptions);
cxt->Q();

That should be it. You can use the more low level methods to write the text, or alternatively draw a path...doesn't matter as long as you call the gs command prior to set the opacity level.
It is OK to combine stages 2 and 3, like this:

cxt->gs(myPage->GetResourcesDictionary().AddExtGStateMapping(gsId));

p.s. there's an example here (and links to code) that shows how to create a single watermark in a form and then reuse that form in multiple pages. again in JS, but can be translated to the C++ operators by mostly moving from camelcasing to titlecasing.

from pdf-writer.

hamedali1336 avatar hamedali1336 commented on July 24, 2024

Thanks for replying

Here is my code now ..

pdfWriter.StartPDF(input, ePDFVersion13);
ObjectsContext objCtx = pdfWriter.GetObjectsContext();
ObjectIDType gsID = objCtx.StartNewIndirectObject();
DictionaryContext* dict = objCtx.StartDictionary();
dict->WriteKey("type");
dict->WriteNameValue("ExtGState");
dict->WriteKey("ca");
objCtx.WriteInteger(0.5); //// cannot find WriteNumber
objCtx.EndLine();
objCtx.EndDictionary(dict);
auto* page = new PDFPage();
page->SetMediaBox(PDFRectangle(0,0,595,842));
std::string gsName = page->GetResourcesDictionary().AddExtGStateMapping(gsID);
PageContentContext* pageContentContext = pdfWriter.StartPageContentContext(page);
PDFUsedFont* font = pdfWriter.GetFontForFile(font_path);
pageContentContext->q();
pageContentContext->gs(gsName);
pageContentContext->BT();
pageContentContext->k(0, 100, 100, 0);
pageContentContext->Tf(font, font_size);
pageContentContext->Tm(1,0,0,1,100,100);
pageContentContext->Tj("Test Text");
pageContentContext->ET();
pageContentContext->Q();
pdfWriter.EndPageContentContext(pageContentContext);
pdfWriter.WritePageAndRelease(page);
pdfWriter.EndPDF();

But opacity not changing

from pdf-writer.

galkahana avatar galkahana commented on July 24, 2024

Hi,
Sorry for not providing a proper example. I just translated lazily from the JS and this resulted in some errors.

To directly deal with errors in the example:

  • this ObjectsContext objCtx = pdfWriter.GetObjectsContext(); should change to this ObjectsContext& objCtx = pdfWriter.GetObjectsContext(); otherwise, we're just creating a copy of the objects context and not actual reference, so what records it has gets lost (specifically - the dictionary object gets overwritten by a later object.
  • this objCtx.WriteInteger(0.5); should change to this objCtx.WriteDouble(0.5);, otherwise int will get rounded to 0 and you will see no watermark.
  • the indirect object should be ended with objCtx.EndIndirectObject();

PDFVersion should probably also change to 14 and not stay in 13, as things like "ca" key are only supported from 14...but that's not a biggy, i think acrobat ignores it.

So the code should be:

pdfWriter.StartPDF(input, ePDFVersion14);
ObjectsContext& objCtx = pdfWriter.GetObjectsContext();
ObjectIDType gsID = objCtx.StartNewIndirectObject();
DictionaryContext* dict = objCtx.StartDictionary();
dict->WriteKey("type");
dict->WriteNameValue("ExtGState");
dict->WriteKey("ca");
objCtx.WriteDouble(0.5);
objCtx.EndLine();
objCtx.EndDictionary(dict);
objCtx.EndIndirectObject();
auto* page = new PDFPage();
page->SetMediaBox(PDFRectangle(0,0,595,842));
std::string gsName = page->GetResourcesDictionary().AddExtGStateMapping(gsID);
PageContentContext* pageContentContext = pdfWriter.StartPageContentContext(page);
PDFUsedFont* font = pdfWriter.GetFontForFile(font_path);
pageContentContext->q();
pageContentContext->gs(gsName);
pageContentContext->BT();
pageContentContext->k(0, 100, 100, 0);
pageContentContext->Tf(font, font_size);
pageContentContext->Tm(1,0,0,1,100,100);
pageContentContext->Tj("Test Text");
pageContentContext->ET();
pageContentContext->Q();
pdfWriter.EndPageContentContext(pageContentContext);
pdfWriter.WritePageAndRelease(page);
pdfWriter.EndPDF();

I added a test called WatermarkTest now to serve as an example.
It also features more higher level commands that's available for writing text and using the dictionary api to write the double.

from pdf-writer.

hamedali1336 avatar hamedali1336 commented on July 24, 2024

Worked like a charm
Thanks :)

from pdf-writer.

hamedali1336 avatar hamedali1336 commented on July 24, 2024

How to use it in modified page ? Not new empty page
Specifically this line

std::string gsName = page->GetResourcesDictionary().AddExtGStateMapping(gsID);

from pdf-writer.

galkahana avatar galkahana commented on July 24, 2024

Hi,
for the sake of another project, for supporting color emojis (#223) i added a SetOpacity operator on content context. hummus manages the creation of relevant extgstate dicts in the background, so you don't have to worry about it. the implementation is also available on the higher level commands with Text options and graphic options now including an opacity factor.

See example here.

from pdf-writer.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.