itext: make a single letter bold within a word

itext, java

Solution

Why do you say you code sample isn't working? I've combined your iText and Android example into a new example: ColoredLetters

I've written a method similar to yours:

private Chunk returnCorrectColor(char letter) {
    if (letter == 'b'){
        return B;
    }
    else if(letter == 'g'){
        return G;
    }
    return new Chunk(String.valueOf(letter), RED_NORMAL);
}

Note that I used some constants:

public static final Font RED_NORMAL = new Font(FontFamily.HELVETICA, 12, Font.NORMAL, BaseColor.RED);
public static final Font BLUE_BOLD = new Font(FontFamily.HELVETICA, 12, Font.BOLD, BaseColor.BLUE);
public static final Font GREEN_ITALIC = new Font(FontFamily.HELVETICA, 12, Font.ITALIC, BaseColor.GREEN);
public static final Chunk B = new Chunk("b", BLUE_BOLD);
public static final Chunk G = new Chunk("g", GREEN_ITALIC);

Now I can construct a `Paragraph` like this:

Paragraph p = new Paragraph();
String s = "all text is written in red, except the letters b and g; they are written in blue and green.";
for (int i = 0; i < s.length(); i++) {
    p.add(returnCorrectColor(s.charAt(i)));
}

The result looks like this: colored_letters.pdf

An alternative would be to use different fonts, where fontB only contains the letter b and fontG only contains the letter g. You could then declare these fonts to the `FontSelector` object, along with a normal font. You could then process the font. For an example using this alternative, please read my answer to the following question: iText changing the font color and size when using fontselector

Updates based on additional questions in the comments

Could i specify the color as a HEX. for example something like `BaseColor(#ffcd03);` I understand that you can specify it like `new BaseColor(0, 0, 255)`, however HEX would be more useful.

Actually, I like the HEX notation more myself, because it is easier for me to recognize certain colors when they are expressed in HEX notation. That's why I often use the HEX notation for integers in Java like this: `new BaseColor(0xFF, 0xCD, 0x03);`

Additionally, there is a `decodeColor()` method in the `HtmlUtilities` class that can be used like this:

BaseColor color = HtmlUtilities.decodeColor("#ffcd03");

is there a way to just define the color and leave the font to the default. Something like this: public static final Font RED_NORMAL = new Font(BaseColor.RED);

You could create the font like this:

new Font(FontFamily.UNDEFINED, 12, Font.UNDEFINED, BaseColor.RED);

Now when you add a `Chunk` with such a font to a `Paragraph`, it should take the font defined at the level of the `Paragraph` (that's how I intended it when I first wrote iText. I should check if this is still true).

My goal is to write a program that colorizes existing PDF files without changing the structure of the PDF. Do you think this approach will work for this purpose (performance etc)?

No, this will not work. If you read the introduction of chapter 6 of the second edition of iText in Action, you'll understand that PDF is not a format that was created for editing. The internal syntax for the sentence shown in the screen shot looks like this:

BT
36 806 Td
0 -16 Td
/F1 12 Tf
1 0 0 rg
(all text is written in red, except the letters ) Tj
0 g
/F2 12 Tf
0 0 1 rg
(b) Tj
0 g
/F1 12 Tf
1 0 0 rg
( and ) Tj
0 g
/F3 12 Tf
0 1 0 rg
(g) Tj
0 g
/F1 12 Tf
1 0 0 rg
(; they are written in ) Tj
0 g
/F2 12 Tf
0 0 1 rg
(b) Tj
0 g
/F1 12 Tf
1 0 0 rg
(lue and ) Tj
0 g
/F3 12 Tf
0 1 0 rg
(g) Tj
0 g
/F1 12 Tf
1 0 0 rg
(reen.) Tj
0 g
0 0 Td
ET

As you can see, the `Tf` operator changes the font:

- `/F1` is the regular font,

- `/F2` is the bold font,

- `/F3` is the italic font.

These names refer to fonts in the `/Resources` dictionary of the page, where you'll find the references to the actual font descriptors.

The `rg` operator changes the color. As we use red, green and blue, you recognize the operande `1 0 0`, `0 1 0` and `0 0 1`.

This looks fairly simple, because we used WINANSI encoding. One could parse the content stream, look for all the PDF string (between `(` and `)` or between `<` and `>`), and introduce `Tf` and `rg` operators.

However: the content stream won't always be as trivial as here. Custom encodings can be used, Unicode can be used,... Take a look at the second screen shot in my answer to the following question: Can't get Czech characters while generating a PDF. You'll understand that your plan to change colors in an existing PDF is a non-trivial task. We have done such a project in the past for one of our customers. It was a project that took several weeks.

Problem

Is it possible to bold out specific letters within a word in itext? Consider this sentence, "this is a word". Could i make all the "i" withing that sentence bold? So the output would be like this: "this is a word" So to get the first word right (this), do i really have to create three chunks for one word and than add all the chunks together? Or is there another approach? With three chunks i mean something like this (i know its not working code but made it like this for readability): ``` Chunk chunk1 = new Chunk("th"); Chunk chunk2 = new Chunk("i", bold); Chunk chunk3 = new Chunk("s"); Paragraph p = new Paragraph(); p.add(chunk1); p.add(chunk2); p.add(chunk3) ``` There has to be a better way. Some "strings" i want colorized as well, like each letter in the string will have a different color, do i have to create chunks for each letter than combine them? With a EditText box in android to change each letter color i could use SpannableString. But its different with itext since it doesnt have the char. I hope you guys understand what i mean, i will post two methods on how i solved in android in an editText box. Now i just want a similar method for writing a colorized and bold text to a pdf. ``` public SpannableString colorizeText(String text) { SpannableString spannableColor = new SpannableString(text); int x = 1; for(char letter : text.toCharArray()){ spannableColor.setSpan(new ForegroundColorSpan(returnCorrectColor(letter)), x-1, x, 0); x++; } return spannableColor; } private int returnCorrectColor(char letter) { String theLetter = Character.toString(letter); if (theLetter.contains("a")){ return Color.BLUE; } else if(theLetter.contains("o")){ return Color.GREEN; } return Color.RED; } ```

Original source

Related problems