191 static { |
191 static { |
192 fontCache = new LSBCacheEntry[CACHE_SIZE]; |
192 fontCache = new LSBCacheEntry[CACHE_SIZE]; |
193 } |
193 } |
194 |
194 |
195 /** |
195 /** |
|
196 * Fill the character buffer cache. Return the buffer length. |
|
197 */ |
|
198 private static int syncCharsBuffer(String s) { |
|
199 int length = s.length(); |
|
200 if ((charsBuffer == null) || (charsBuffer.length < length)) { |
|
201 charsBuffer = s.toCharArray(); |
|
202 } else { |
|
203 s.getChars(0, length, charsBuffer, 0); |
|
204 } |
|
205 return length; |
|
206 } |
|
207 |
|
208 /** |
196 * checks whether TextLayout is required to handle characters. |
209 * checks whether TextLayout is required to handle characters. |
197 * |
210 * |
198 * @param text characters to be tested |
211 * @param text characters to be tested |
199 * @param start start |
212 * @param start start |
200 * @param limit limit |
213 * @param limit limit |
351 */ |
364 */ |
352 public static int stringWidth(JComponent c, FontMetrics fm, String string){ |
365 public static int stringWidth(JComponent c, FontMetrics fm, String string){ |
353 if (string == null || string.equals("")) { |
366 if (string == null || string.equals("")) { |
354 return 0; |
367 return 0; |
355 } |
368 } |
356 return fm.stringWidth(string); |
369 boolean needsTextLayout = ((c != null) && |
|
370 (c.getClientProperty(TextAttribute.NUMERIC_SHAPING) != null)); |
|
371 if (needsTextLayout) { |
|
372 synchronized(charsBufferLock) { |
|
373 int length = syncCharsBuffer(string); |
|
374 needsTextLayout = isComplexLayout(charsBuffer, 0, length); |
|
375 } |
|
376 } |
|
377 if (needsTextLayout) { |
|
378 TextLayout layout = createTextLayout(c, string, |
|
379 fm.getFont(), fm.getFontRenderContext()); |
|
380 return (int) layout.getAdvance(); |
|
381 } else { |
|
382 return fm.stringWidth(string); |
|
383 } |
357 } |
384 } |
358 |
385 |
359 |
386 |
360 /** |
387 /** |
361 * Clips the passed in String to the space provided. |
388 * Clips the passed in String to the space provided. |
392 */ |
419 */ |
393 public static String clipString(JComponent c, FontMetrics fm, |
420 public static String clipString(JComponent c, FontMetrics fm, |
394 String string, int availTextWidth) { |
421 String string, int availTextWidth) { |
395 // c may be null here. |
422 // c may be null here. |
396 String clipString = "..."; |
423 String clipString = "..."; |
397 int stringLength = string.length(); |
|
398 availTextWidth -= SwingUtilities2.stringWidth(c, fm, clipString); |
424 availTextWidth -= SwingUtilities2.stringWidth(c, fm, clipString); |
399 if (availTextWidth <= 0) { |
|
400 //can not fit any characters |
|
401 return clipString; |
|
402 } |
|
403 |
|
404 boolean needsTextLayout; |
425 boolean needsTextLayout; |
405 |
426 |
406 synchronized (charsBufferLock) { |
427 synchronized (charsBufferLock) { |
407 if (charsBuffer == null || charsBuffer.length < stringLength) { |
428 int stringLength = syncCharsBuffer(string); |
408 charsBuffer = string.toCharArray(); |
|
409 } else { |
|
410 string.getChars(0, stringLength, charsBuffer, 0); |
|
411 } |
|
412 needsTextLayout = |
429 needsTextLayout = |
413 isComplexLayout(charsBuffer, 0, stringLength); |
430 isComplexLayout(charsBuffer, 0, stringLength); |
414 if (!needsTextLayout) { |
431 if (!needsTextLayout) { |
415 int width = 0; |
432 int width = 0; |
416 for (int nChars = 0; nChars < stringLength; nChars++) { |
433 for (int nChars = 0; nChars < stringLength; nChars++) { |
423 } |
440 } |
424 } |
441 } |
425 if (needsTextLayout) { |
442 if (needsTextLayout) { |
426 FontRenderContext frc = getFontRenderContext(c, fm); |
443 FontRenderContext frc = getFontRenderContext(c, fm); |
427 AttributedString aString = new AttributedString(string); |
444 AttributedString aString = new AttributedString(string); |
|
445 if (c != null) { |
|
446 aString.addAttribute(TextAttribute.NUMERIC_SHAPING, |
|
447 c.getClientProperty(TextAttribute.NUMERIC_SHAPING)); |
|
448 } |
428 LineBreakMeasurer measurer = |
449 LineBreakMeasurer measurer = |
429 new LineBreakMeasurer(aString.getIterator(), frc); |
450 new LineBreakMeasurer(aString.getIterator(), frc); |
430 int nChars = measurer.nextOffset(availTextWidth); |
451 int nChars = measurer.nextOffset(availTextWidth); |
431 string = string.substring(0, nChars); |
452 string = string.substring(0, nChars); |
432 |
453 |
463 * it to fit in the screen width. This distributes the spacing |
484 * it to fit in the screen width. This distributes the spacing |
464 * more evenly than directly laying out to the screen advances. |
485 * more evenly than directly laying out to the screen advances. |
465 */ |
486 */ |
466 float screenWidth = (float) |
487 float screenWidth = (float) |
467 g2d.getFont().getStringBounds(text, DEFAULT_FRC).getWidth(); |
488 g2d.getFont().getStringBounds(text, DEFAULT_FRC).getWidth(); |
468 TextLayout layout = new TextLayout(text, g2d.getFont(), |
489 TextLayout layout = createTextLayout(c, text, g2d.getFont(), |
469 g2d.getFontRenderContext()); |
490 g2d.getFontRenderContext()); |
470 |
491 |
471 layout = layout.getJustifiedLayout(screenWidth); |
492 layout = layout.getJustifiedLayout(screenWidth); |
472 /* Use alternate print color if specified */ |
493 /* Use alternate print color if specified */ |
473 Color col = g2d.getColor(); |
494 Color col = g2d.getColor(); |
503 g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, |
524 g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, |
504 info.lcdContrastHint); |
525 info.lcdContrastHint); |
505 } |
526 } |
506 } |
527 } |
507 |
528 |
508 g.drawString(text, x, y); |
529 boolean needsTextLayout = ((c != null) && |
|
530 (c.getClientProperty(TextAttribute.NUMERIC_SHAPING) != null)); |
|
531 if (needsTextLayout) { |
|
532 synchronized(charsBufferLock) { |
|
533 int length = syncCharsBuffer(text); |
|
534 needsTextLayout = isComplexLayout(charsBuffer, 0, length); |
|
535 } |
|
536 } |
|
537 if (needsTextLayout) { |
|
538 TextLayout layout = createTextLayout(c, text, g2.getFont(), |
|
539 g2.getFontRenderContext()); |
|
540 layout.draw(g2, x, y); |
|
541 } else { |
|
542 g.drawString(text, x, y); |
|
543 } |
509 |
544 |
510 if (oldAAValue != null) { |
545 if (oldAAValue != null) { |
511 g2.setRenderingHint(KEY_TEXT_ANTIALIASING, oldAAValue); |
546 g2.setRenderingHint(KEY_TEXT_ANTIALIASING, oldAAValue); |
512 } |
547 } |
513 if (oldContrast != null) { |
548 if (oldContrast != null) { |
545 int underlineRectWidth = 0; |
580 int underlineRectWidth = 0; |
546 boolean isPrinting = isPrinting(g); |
581 boolean isPrinting = isPrinting(g); |
547 boolean needsTextLayout = isPrinting; |
582 boolean needsTextLayout = isPrinting; |
548 if (!needsTextLayout) { |
583 if (!needsTextLayout) { |
549 synchronized (charsBufferLock) { |
584 synchronized (charsBufferLock) { |
550 if (charsBuffer == null || charsBuffer.length < textLength) { |
585 syncCharsBuffer(text); |
551 charsBuffer = text.toCharArray(); |
|
552 } else { |
|
553 text.getChars(0, textLength, charsBuffer, 0); |
|
554 } |
|
555 needsTextLayout = |
586 needsTextLayout = |
556 isComplexLayout(charsBuffer, 0, textLength); |
587 isComplexLayout(charsBuffer, 0, textLength); |
557 } |
588 } |
558 } |
589 } |
559 if (!needsTextLayout) { |
590 if (!needsTextLayout) { |
565 charAt(underlinedIndex)); |
596 charAt(underlinedIndex)); |
566 } else { |
597 } else { |
567 Graphics2D g2d = getGraphics2D(g); |
598 Graphics2D g2d = getGraphics2D(g); |
568 if (g2d != null) { |
599 if (g2d != null) { |
569 TextLayout layout = |
600 TextLayout layout = |
570 new TextLayout(text, g2d.getFont(), |
601 createTextLayout(c, text, g2d.getFont(), |
571 g2d.getFontRenderContext()); |
602 g2d.getFontRenderContext()); |
572 if (isPrinting) { |
603 if (isPrinting) { |
573 float screenWidth = (float)g2d.getFont(). |
604 float screenWidth = (float)g2d.getFont(). |
574 getStringBounds(text, DEFAULT_FRC).getWidth(); |
605 getStringBounds(text, DEFAULT_FRC).getWidth(); |
575 layout = layout.getJustifiedLayout(screenWidth); |
606 layout = layout.getJustifiedLayout(screenWidth); |
726 FontRenderContext frc = getFontRenderContext(c); |
757 FontRenderContext frc = getFontRenderContext(c); |
727 if (frc != null && |
758 if (frc != null && |
728 !isFontRenderContextPrintCompatible |
759 !isFontRenderContextPrintCompatible |
729 (deviceFontRenderContext, frc)) { |
760 (deviceFontRenderContext, frc)) { |
730 TextLayout layout = |
761 TextLayout layout = |
731 new TextLayout(new String(data,offset,length), |
762 createTextLayout(c, new String(data, offset, length), |
732 g2d.getFont(), |
763 g2d.getFont(), |
733 deviceFontRenderContext); |
764 deviceFontRenderContext); |
734 float screenWidth = (float)g2d.getFont(). |
765 float screenWidth = (float)g2d.getFont(). |
735 getStringBounds(data, offset, offset + length, frc). |
766 getStringBounds(data, offset, offset + length, frc). |
736 getWidth(); |
767 getWidth(); |
842 if (isPrinting) { |
873 if (isPrinting) { |
843 g.setColor(col); |
874 g.setColor(col); |
844 } |
875 } |
845 |
876 |
846 return retVal; |
877 return retVal; |
|
878 } |
|
879 |
|
880 private static TextLayout createTextLayout(JComponent c, String s, |
|
881 Font f, FontRenderContext frc) { |
|
882 Object shaper = (c == null ? |
|
883 null : c.getClientProperty(TextAttribute.NUMERIC_SHAPING)); |
|
884 if (shaper == null) { |
|
885 return new TextLayout(s, f, frc); |
|
886 } else { |
|
887 Map<TextAttribute, Object> a = new HashMap<TextAttribute, Object>(); |
|
888 a.put(TextAttribute.FONT, f); |
|
889 a.put(TextAttribute.NUMERIC_SHAPING, shaper); |
|
890 return new TextLayout(s, a, frc); |
|
891 } |
847 } |
892 } |
848 |
893 |
849 /* |
894 /* |
850 * Checks if two given FontRenderContexts are compatible for printing. |
895 * Checks if two given FontRenderContexts are compatible for printing. |
851 * We can't just use equals as we want to exclude from the comparison : |
896 * We can't just use equals as we want to exclude from the comparison : |