0

I use the following function to convert a string to a bitmap in Android:

 static public Bitmap createBitmapFromText(String printText, int textSize, int printWidth, Typeface typeface) {
    Paint paint = new Paint();
    Bitmap bitmap;
    Canvas canvas;

    paint.setTextSize(textSize);
    paint.setTypeface(typeface);

    paint.getTextBounds(printText, 0, printText.length(), new Rect());

    TextPaint textPaint = new TextPaint(paint);
    android.text.StaticLayout staticLayout = new StaticLayout(printText, textPaint, printWidth, Layout.Alignment.ALIGN_NORMAL, 1, 0, false);


    // Create bitmap
    bitmap = Bitmap.createBitmap(staticLayout.getWidth(), staticLayout.getHeight(), Bitmap.Config.ARGB_8888);

    // Create canvas
    canvas = new Canvas(bitmap);
    canvas.drawColor(Color.WHITE);
    canvas.translate(0, 0);
    staticLayout.draw(canvas);

    return bitmap;
}

I want to convert it so I can create a Bitmap with different font styles, with something like the following:

static public Bitmap createBitmapFromText(String[] texts, int[] textSizes, int printWidth, Typeface typeface) {
}

Is there any way I can append multiple TextPaint objects with different styles into a StaticLayout?

The outcome will be something like

#invoice-POS{
  padding:2mm;
  margin: 0 auto;
  width: 44mm;
  background: #FFF;
  
h1{
  font-size: 1.5em;
  color: #222;
}
h2{font-size: .9em;}
h3{
  font-size: 1.2em;
  font-weight: 300;
  line-height: 2em;
}
p{
  font-size: .7em;
  color: #666;
  line-height: 1.2em;
}
 
#top, #mid,#bot{ /* Targets all id with 'col-' */
  border-bottom: 1px solid #EEE;
}

#top{min-height: 100px;}
#mid{min-height: 80px;} 
#bot{ min-height: 50px;}

#top .logo{
  //float: left;
 height: 60px;
 width: 60px;
 background: url(http://michaeltruong.ca/images/logo1.png) no-repeat;
 background-size: 60px 60px;
}
.clientlogo{
  float: left;
 height: 60px;
 width: 60px;
 background: url(http://michaeltruong.ca/images/client.jpg) no-repeat;
 background-size: 60px 60px;
  border-radius: 50px;
}
.info{
  display: block;
  //float:left;
  margin-left: 0;
}
.title{
  float: right;
}
.title p{text-align: right;} 
table{
  width: 100%;
  border-collapse: collapse;
}
td{
  //padding: 5px 0 5px 15px;
  //border: 1px solid #EEE
}
.tabletitle{
  //padding: 5px;
  font-size: .5em;
  background: #EEE;
}
.service{border-bottom: 1px solid #EEE;}
.item{width: 24mm;}
.itemtext{font-size: .5em;}
#legalcopy{
  margin-top: 5mm;
}

  
  
}
  <div id="invoice-POS">
    
    <center id="top">
      <div class="logo"></div>
    </center><!--End InvoiceTop-->
    
    <div id="mid">
      <div class="info">
        <h2>Contact Info</h2>
        <p> 
            Address : street city, state 0000</br>
            Email   : JohnDoe@gmail.com</br>
            Phone   : 555-555-5555</br>
        </p>
      </div>
    </div><!--End Invoice Mid-->
    
    <div id="bot">

     <div id="table">
      <table>
       <tr class="tabletitle">
        <td class="item"><h2>Item</h2></td>
        <td class="Hours"><h2>Qty</h2></td>
        <td class="Rate"><h2>Sub Total</h2></td>
       </tr>

       <tr class="service">
        <td class="tableitem"><p class="itemtext">Communication</p></td>
        <td class="tableitem"><p class="itemtext">5</p></td>
        <td class="tableitem"><p class="itemPrice">$375.00</p></td>
       </tr>

       <tr class="service">
        <td class="tableitem"><p class="itemtext">Asset Gathering</p></td>
        <td class="tableitem"><p class="itemtext">3</p></td>
        <td class="tableitem"><p class="itemPrice">$225.00</p></td>
       </tr>

       <tr class="service">
        <td class="tableitem"><p class="itemtext">Design Development</p></td>
        <td class="tableitem"><p class="itemtext">5</p></td>
        <td class="tableitem"><p class="itemPrice">$375.00</p></td>
       </tr>

       <tr class="service">
        <td class="tableitem"><p class="itemtext">Animation</p></td>
        <td class="tableitem"><p class="itemtext">20</p></td>
        <td class="tableitem"><p class="itemPrice">$1500.00</p></td>
       </tr>

       <tr class="service">
        <td class="tableitem"><p class="itemtext">Animation Revisions</p></td>
        <td class="tableitem"><p class="itemtext">10</p></td>
        <td class="tableitem"><p class="itemPrice">$750.00</p></td>
       </tr>


       <tr class="tabletitle">
        <td></td>
        <td class="Rate"><h2>tax</h2></td>
        <td class="payment"><h2>$419.25</h2></td>
       </tr>

       <tr class="tabletitle">
        <td></td>
        <td class="Rate"><h2>Total</h2></td>
        <td class="payment"><h2>$3,644.25</h2></td>
       </tr>

      </table>
     </div><!--End Table-->

     <div id="legalcopy">
      <p class="legal"><strong>Thank you for your business!</strong>  Payment is expected within 31 days; please process this invoice within that time. There will be a 5% interest charge per month on late invoices. 
      </p>
     </div>

    </div><!--End InvoiceBot-->
  </div><!--End Invoice-->

UPDATE: I modified the function to get an array of formatted texts instead of a single String and i use SpannableStrings as dpskink suggested.

class FormattedString {
    public FormattedString(String text, int fontSize) {
        this.text = text;
        this.fontSize = fontSize;
    }

    public String text;

    public int fontSize;
}

static public Bitmap createBitmapFromTexts(FormattedString[] formattedStrings, int textSize, int printWidth, Typeface typeface) {
    Paint paint = new Paint();
    Bitmap bitmap;
    Canvas canvas;

    paint.setTextSize(textSize);
    paint.setTypeface(typeface);

    paint.getTextBounds(formattedStrings[0].text, 0, formattedStrings[0].text.length(), new Rect());
    TextPaint textPaint = new TextPaint(paint);
    SpannableString[] spannableStrings = new SpannableString[formattedStrings.length];
    for (int i = 0; i < formattedStrings.length; i++) {
        SpannableString spannableString = new SpannableString(formattedStrings[i].text);
        spannableString.setSpan(new RelativeSizeSpan(formattedStrings[i].fontSize), 0, formattedStrings[i].text.length(), 0);
        spannableStrings[i] = spannableString;
    }

    CharSequence text = TextUtils.concat(spannableStrings);

    android.text.StaticLayout staticLayout = new StaticLayout(text, textPaint, printWidth, Layout.Alignment.ALIGN_NORMAL, 1, 0, false);

    // Create bitmap
    bitmap = Bitmap.createBitmap(staticLayout.getWidth(), staticLayout.getHeight(), Bitmap.Config.ARGB_8888);

    // Create canvas
    canvas = new Canvas(bitmap);
    canvas.drawColor(Color.WHITE);
    canvas.translate(0, 0);
    staticLayout.draw(canvas);

    return bitmap;
}

And from my Main Activity:

    int textSize = 25;
    Typeface typeface = Typeface.create(Typeface.MONOSPACE, Typeface.NORMAL);
    FormattedString[] formattedStrings = {
            new FormattedString("****ORDER NUMBER 1111***", 1),
            new FormattedString("****222", 2),
            new FormattedString("*33***", 3),
            new FormattedString("****222*", 2),
            new FormattedString("****111***", 1),
            new FormattedString("****222***", 2)
    };

    return createBitmapFromTexts(formattedStrings, textSize, PrinterSettingConstant.PAPER_SIZE_THREE_INCH, typeface);

Seems like it is working. The only thing that troubles me is the Paint/TextPaint objects which are created just for the StaticLayout constructor with dump data...

  • no `StaticLayout` takes only one `TextPaint` – pskink Dec 18 '19 at 09:06
  • So I have to create multiple StaticLayouts, one for every line of text? – Giannis Karageorgiou Dec 18 '19 at 09:06
  • not really: you have to use spans, see `SpannableStringBuilder` – pskink Dec 18 '19 at 09:07
  • I don't quite understand how to use the SpannableString here. With the TextPaint the text that is rendered in the Canvas is automatically wrapped if it reaches the end of the provided width. How is this going to work with SpannableString? Should i measure the width of the text? – Giannis Karageorgiou Dec 18 '19 at 09:23
  • ok, so what text to you want to draw? just different text size? if so use `RelativeSizeSpan` / `AbsoluteSizeSpan` then call `SpannableStringBuilder.setSpan` with one of those spans – pskink Dec 18 '19 at 09:26
  • I want to create printable receipt images. I 've updated the question and included a snippet – Giannis Karageorgiou Dec 18 '19 at 09:53
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/204474/discussion-between-pskink-and-giannis-karageorgiou). – pskink Dec 18 '19 at 09:59
  • post an image with those "different font size" texts - did you try `RelativeSizeSpan` / `AbsoluteSizeSpan` - if so, what did not work? – pskink Dec 18 '19 at 10:00
  • I would suggest the following procedure: 1. making a fragment/Activity with your desired layout 2. fill data when creating the fragment/Activity 3. take a screenshot of the final view(Parent layout in the XML file for this activity/fragment). It is faster to implement it this way and much more customizable for your purpose. – Harshvardhan Joshi Dec 18 '19 at 12:56

0 Answers0