Skip to content

Commit

Permalink
#228 Reworked letter-spacing to work at the inline text level.
Browse files Browse the repository at this point in the history
So now supports different letter-spacing values at the inline level rather than just at the block level. Also supports a letter-spacing on the first-letter psuedo element.
  • Loading branch information
danfickle committed Jul 29, 2018
1 parent f83d356 commit 89bb1d4
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,13 @@ public class Breaker {
public static void breakFirstLetter(LayoutContext c, LineBreakContext context,
int avail, CalculatedStyle style) {
FSFont font = style.getFSFont(c);
float letterSpacing = style.hasLetterSpacing() ?
style.getFloatPropertyProportionalWidth(CSSName.LETTER_SPACING, 0, c) :
0f;

context.setEnd(getFirstLetterEnd(context.getMaster(), context.getStart()));
context.setWidth(c.getTextRenderer().getWidth(
c.getFontContext(), font, context.getCalculatedSubstring()));
c.getFontContext(), font, context.getCalculatedSubstring()) + (int) letterSpacing);

if (context.getWidth() > avail) {
context.setNeedsNewLine(true);
Expand Down Expand Up @@ -122,9 +126,8 @@ public static void doBreakText(

FSFont font = style.getFSFont(c);

// FIXME: avail is not the right width here. Should be box's width.
float letterSpacing = style.hasLetterSpacing() ?
style.getFloatPropertyProportionalWidth(CSSName.LETTER_SPACING, avail, c) :
style.getFloatPropertyProportionalWidth(CSSName.LETTER_SPACING, 0, c) :
0f;

String currentString = context.getStartSubstring();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,11 @@ public static void layoutContent(LayoutContext c, BlockBox box, int initialY, in
lbContext.saveEnd();
InlineText inlineText = layoutText(
c, iB.getStyle(), remainingWidth - fit, lbContext, false, iB.getTextDirection());

if (iB.getStyle().hasLetterSpacing()) {
inlineText.setLetterSpacing(iB.getStyle().getFloatPropertyProportionalWidth(CSSName.LETTER_SPACING, 0, c));
}

if (lbContext.isUnbreakable() && ! currentLine.isContainsContent()) {
int delta = c.getBlockFormattingContext().getNextLineBoxDelta(c, currentLine, maxAvailableWidth);
if (delta > 0) {
Expand Down Expand Up @@ -396,6 +401,11 @@ private static InlineLayoutBox addFirstLetterBox(LayoutContext c, LineBox curren
current.setContainsContent(true);

InlineText text = layoutText(c, iB.getStyle(), remainingWidth, lbContext, true, textDirection);

if (iB.getStyle().hasLetterSpacing()) {
text.setLetterSpacing(iB.getStyle().getFloatPropertyProportionalWidth(CSSName.LETTER_SPACING, 0, c));
}

iB.addInlineChild(c, text);
iB.setInlineWidth(text.getWidth());

Expand Down Expand Up @@ -940,6 +950,7 @@ private static InlineText layoutText(LayoutContext c, CalculatedStyle style, int
LineBreakContext lbContext, boolean needFirstLetter, byte textDirection) {
InlineText result = new InlineText();
String masterText = lbContext.getMaster();

if (needFirstLetter) {
masterText = TextUtil.transformFirstLetterText(masterText, style);
lbContext.setMaster(masterText);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,19 @@ public void drawText(RenderingContext c, InlineText inlineText) {
setColor(iB.getStyle().getColor());
setFont(iB.getStyle().getFSFont(c));
setFontSpecification(iB.getStyle().getFontSpecification());
if (inlineText.getParent().getStyle().isTextJustify() || inlineText.getParent().getStyle().hasLetterSpacing()) {
if (inlineText.getLetterSpacing() != 0f) {
JustificationInfo info = new JustificationInfo();
info.setNonSpaceAdjust(inlineText.getLetterSpacing());
info.setSpaceAdjust(inlineText.getLetterSpacing());
c.getTextRenderer().drawString(
c.getOutputDevice(),
text,
iB.getAbsX() + inlineText.getX(), iB.getAbsY() + iB.getBaseline(),
info);
} else if (inlineText.getParent().getStyle().isTextJustify()) {
// NOTE: Use of letter-spacing turns off justification
JustificationInfo info = inlineText.getParent().getLineBox().getJustificationInfo();

if (info != null) {
c.getTextRenderer().drawString(
c.getOutputDevice(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,7 @@ protected void layoutInlineChildren(
satisfyWidowsAndOrphans(c, contentStart, tryAgain);
}

if (tryAgain && (getStyle().isTextJustify() || getStyle().hasLetterSpacing())) {
if (tryAgain && (getStyle().isTextJustify())) {
justifyText(c);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public class InlineText {
private boolean _trimmedTrailingSpace;
private Text _textNode;
private byte _textDirection;
private float _letterSpacing;

/**
* @param direction either LTR or RTL from BidiSplitter interface.
Expand All @@ -74,6 +75,14 @@ public byte getTextDirection() {
return this._textDirection;
}

public void setLetterSpacing(float letterSpacing) {
this._letterSpacing = letterSpacing;
}

public float getLetterSpacing() {
return this._letterSpacing;
}

public void trimTrailingSpace(LayoutContext c) {
if (! isEmpty() && _masterText.charAt(_end-1) == ' ') {
_end--;
Expand Down Expand Up @@ -311,6 +320,12 @@ private boolean isTrimmedTrailingSpace() {
}

public void countJustifiableChars(CharCounts counts) {
if (getLetterSpacing() != 0f) {
// We can't mess with character spacing if
// letter spacing is already explicitly set.
return;
}

String s = getSubstring();
int len = s.length();
int spaces = 0;
Expand All @@ -330,6 +345,12 @@ public void countJustifiableChars(CharCounts counts) {
}

public float calcTotalAdjustment(JustificationInfo info) {
if (getLetterSpacing() != 0f) {
// We can't mess with character spacing if
// letter spacing is already explicitly set.
return 0f;
}

String s = getSubstring();
int len = s.length();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,15 +217,9 @@ public void align(boolean dynamic, CssContext c) {
}

public void justify(CssContext c) {
// NOTE: Use of letter-spacing prelcludes justification

if (getParent().getStyle().hasLetterSpacing()) {
float letterSpacing = getParent().getStyle().getFloatPropertyProportionalWidth(CSSName.LETTER_SPACING, getParent().getContentWidth(), c);
JustificationInfo info = new JustificationInfo();
info.setNonSpaceAdjust(letterSpacing);
info.setSpaceAdjust(letterSpacing);

adjustChildren(info);
setJustificationInfo(info);
// Do nothing, letter-spacing turns off text justification.
} else if (! isLastLineWithContent()) {
int leftFloatDistance = getFloatDistances().getLeftFloatDistance();
int rightFloatDistance = getFloatDistances().getRightFloatDistance();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,8 @@ public void drawStringFast(String s, float x, float y, JustificationInfo info, F
_cp.setTextMatrix((float) mx[0], b, c, (float) mx[3], (float) mx[4], (float) mx[5]);

if (info != null ) {
// Note: Justification info is also used
// to implement letter-spacing CSS property.
// Justification must be done through TJ rendering
// because Tw param does not work for UNICODE fonts
Object[] array = makeJustificationArray(s, info);
Expand Down

0 comments on commit 89bb1d4

Please sign in to comment.