1 7 8 22 23 package java.awt.font; 24 25 import java.text.BreakIterator ; 26 import java.text.CharacterIterator ; 27 import java.text.AttributedCharacterIterator ; 28 import java.awt.font.FontRenderContext ; 29 30 229 230 public final class LineBreakMeasurer { 231 232 private BreakIterator breakIter; 233 private int start; 234 private int pos; 235 private int limit; 236 private TextMeasurer measurer; 237 private CharArrayIterator charIter; 238 239 258 public LineBreakMeasurer(AttributedCharacterIterator text, FontRenderContext frc) { 259 this(text, BreakIterator.getLineInstance(), frc); 260 } 261 262 284 public LineBreakMeasurer(AttributedCharacterIterator text, 285 BreakIterator breakIter, 286 FontRenderContext frc) { 287 if (text.getEndIndex() - text.getBeginIndex() < 1) { 288 throw new IllegalArgumentException ("Text must contain at least one character."); 289 } 290 291 this.breakIter = breakIter; 292 this.measurer = new TextMeasurer (text, frc); 293 this.limit = text.getEndIndex(); 294 this.pos = this.start = text.getBeginIndex(); 295 296 charIter = new CharArrayIterator (measurer.getChars(), this.start); 297 this.breakIter.setText(charIter); 298 } 299 300 309 public int nextOffset(float wrappingWidth) { 310 return nextOffset(wrappingWidth, limit, false); 311 } 312 313 330 public int nextOffset(float wrappingWidth, int offsetLimit, 331 boolean requireNextWord) { 332 333 int nextOffset = pos; 334 335 if (pos < limit) { 336 if (offsetLimit <= pos) { 337 throw new IllegalArgumentException ("offsetLimit must be after current position"); 338 } 339 340 int charAtMaxAdvance = 341 measurer.getLineBreakIndex(pos, wrappingWidth); 342 343 if (charAtMaxAdvance == limit) { 344 nextOffset = limit; 345 } 346 else if (Character.isWhitespace(measurer.getChars()[charAtMaxAdvance-start])) { 347 nextOffset = breakIter.following(charAtMaxAdvance); 348 } 349 else { 350 352 int testPos = charAtMaxAdvance + 1; 358 if (testPos == limit) { 359 breakIter.last(); 360 nextOffset = breakIter.previous(); 361 } 362 else { 363 nextOffset = breakIter.preceding(testPos); 364 } 365 366 if (nextOffset <= pos) { 367 if (requireNextWord) { 369 nextOffset = pos; 370 } 371 else { 372 nextOffset = Math.max(pos+1, charAtMaxAdvance); 373 } 374 } 375 } 376 } 377 378 if (nextOffset > offsetLimit) { 379 nextOffset = offsetLimit; 380 } 381 382 return nextOffset; 383 } 384 385 394 public TextLayout nextLayout(float wrappingWidth) { 395 return nextLayout(wrappingWidth, limit, false); 396 } 397 398 418 public TextLayout nextLayout(float wrappingWidth, int offsetLimit, 419 boolean requireNextWord) { 420 421 if (pos < limit) { 422 int layoutLimit = nextOffset(wrappingWidth, offsetLimit, requireNextWord); 423 if (layoutLimit == pos) { 424 return null; 425 } 426 427 TextLayout result = measurer.getLayout(pos, layoutLimit); 428 pos = layoutLimit; 429 430 return result; 431 } else { 432 return null; 433 } 434 } 435 436 442 public int getPosition() { 443 return pos; 444 } 445 446 456 public void setPosition(int newPosition) { 457 if (newPosition < start || newPosition > limit) { 458 throw new IllegalArgumentException ("position is out of range"); 459 } 460 pos = newPosition; 461 } 462 463 478 public void insertChar(AttributedCharacterIterator newParagraph, 479 int insertPos) { 480 481 measurer.insertChar(newParagraph, insertPos); 482 483 limit = newParagraph.getEndIndex(); 484 pos = start = newParagraph.getBeginIndex(); 485 486 charIter.reset(measurer.getChars(), newParagraph.getBeginIndex()); 487 breakIter.setText(charIter); 488 } 489 490 504 public void deleteChar(AttributedCharacterIterator newParagraph, 505 int deletePos) { 506 507 measurer.deleteChar(newParagraph, deletePos); 508 509 limit = newParagraph.getEndIndex(); 510 pos = start = newParagraph.getBeginIndex(); 511 512 charIter.reset(measurer.getChars(), start); 513 breakIter.setText(charIter); 514 } 515 } 516 517 | Popular Tags |