How to make a single letter bold within a word?

Category: 
Tags: colored textboldfont colorfontsiText 5

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" within that sentence bold? I want the output to 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:

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. I want to colorize some "strings" as well, so that each letter in the string will have a different color. Do I have to create chunks for each letter than combine them?

Posted on StackOverflow on Nov 22, 2014 by user3711421

Take a look at the following example: ColoredLetters

I've written this method that automates what you describe:

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

Color applied to text
Color applied to text

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 question: "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. 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: How to use Cyrillic characters in 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.