[DEV] add capability in font render system

This commit is contained in:
Edouard DUPIN 2021-05-29 00:52:11 +02:00
parent d366431a71
commit 9b8e5c4f35
5 changed files with 64 additions and 34 deletions

View File

@ -1,9 +1,9 @@
package org.atriasoft.esvg; package org.atriasoft.esvg;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.atriasoft.esvg.font.Glyph; import org.atriasoft.esvg.font.Glyph;
import org.atriasoft.esvg.font.Kerning; import org.atriasoft.esvg.font.Kerning;
@ -259,12 +259,12 @@ public class EsvgFont {
public Vector2i calculateTextSize(final int fontSize, final String data) { public Vector2i calculateTextSize(final int fontSize, final String data) {
boolean withKerning = true; boolean withKerning = true;
int widthOut = calculateWidth(data, fontSize, withKerning); int widthOut = calculateWidth(data, fontSize, withKerning);
int realSize = calculateFontRealHeight(fontSize); int realSize = calculateFontRealHeight(fontSize);
return new Vector2i(widthOut, realSize);
/*
float scale = (float) realSize / (float) this.unitsPerEm; float scale = (float) realSize / (float) this.unitsPerEm;
Weight weight = new Weight(new Vector2i(widthOut, realSize));
int offsetWriting = 0; int offsetWriting = 0;
int lastValue = 0; int lastValue = 0;
for (char uVal : data.toCharArray()) { for (char uVal : data.toCharArray()) {
@ -283,6 +283,7 @@ public class EsvgFont {
offsetWriting += advenceXLocal; offsetWriting += advenceXLocal;
} }
return new Vector2i(offsetWriting, realSize); return new Vector2i(offsetWriting, realSize);
*/
} }
public int calculateWidth(final int uVal, final int fontSize) { public int calculateWidth(final int uVal, final int fontSize) {
@ -302,7 +303,8 @@ public class EsvgFont {
public int calculateWidth(final String data, final int fontSize, final boolean withKerning) { public int calculateWidth(final String data, final int fontSize, final boolean withKerning) {
int realSize = calculateFontRealHeight(fontSize); int realSize = calculateFontRealHeight(fontSize);
float scale = (float) realSize / (float) this.unitsPerEm; float scale = (float) realSize / (float) this.unitsPerEm;
int out = 0; //Log.error("scale =" + scale+ " font size = " + fontSize + " realSize=" + realSize);
float offsetWriting = 0;
int lastValue = 0; int lastValue = 0;
for (char uVal : data.toCharArray()) { for (char uVal : data.toCharArray()) {
Glyph glyph = getGlyph(uVal); Glyph glyph = getGlyph(uVal);
@ -311,12 +313,15 @@ public class EsvgFont {
continue; continue;
} }
if (withKerning) { if (withKerning) {
out -= glyph.getKerning(lastValue) * scale; offsetWriting -= glyph.getKerning(lastValue) * scale;
lastValue = uVal; lastValue = uVal;
} }
out += glyph.getHorizAdvX() * scale;
float advenceXLocal = glyph.getHorizAdvX() * scale;
offsetWriting += advenceXLocal;
//Log.error("offset X =" + offsetWriting + " + " + advenceXLocal + " " + uVal);
} }
return out; return (int)offsetWriting;
} }
/** /**
@ -402,7 +407,7 @@ public class EsvgFont {
Weight weight = new Weight(new Vector2i(widthOut, realSize)); Weight weight = new Weight(new Vector2i(widthOut, realSize));
int offsetWriting = 0; float offsetWriting = 0;
int lastValue = 0; int lastValue = 0;
for (char uVal : data.toCharArray()) { for (char uVal : data.toCharArray()) {
Glyph glyph = getGlyph(uVal); Glyph glyph = getGlyph(uVal);
@ -423,7 +428,7 @@ public class EsvgFont {
PathModel model = glyph.getModel(); PathModel model = glyph.getModel();
if (model != null) { if (model != null) {
Weight redered = model.drawFill(calculateWidthRendering((int) uVal, fontSize), transform, 8, config); Weight redered = model.drawFill(calculateWidthRendering((int) uVal, fontSize), transform, 8, config);
weight.fusion(redered, offsetWriting, 0); weight.fusion(redered, (int)offsetWriting, 0);
} }
offsetWriting += advenceXLocal; offsetWriting += advenceXLocal;

View File

@ -94,6 +94,10 @@ public class GraphicContext {
public int getTextHeight() { public int getTextHeight() {
return getTextHeight(Configs.getConfigFonts().getSize()); return getTextHeight(Configs.getConfigFonts().getSize());
} }
public int getTextSize() {
return Configs.getConfigFonts().getSize();
}
public int getTextHeight(final float height) { public int getTextHeight(final float height) {
return FontCache.getFont(Configs.getConfigFonts().getName(), false, false).calculateFontRealHeight((int) height); return FontCache.getFont(Configs.getConfigFonts().getName(), false, false).calculateFontRealHeight((int) height);
@ -258,11 +262,11 @@ public class GraphicContext {
} }
public void text(final Vector2f position, final float height, final String data) { public void text(final Vector2f position, final float height, final String data) {
this.document.addElement(new Text(position, height, data, this.paintState.clone())); this.document.addElement(new Text(position, Configs.getConfigFonts().getName(), height, data, this.paintState.clone()));
} }
public void text(final Vector2f position, final String data) { public void text(final Vector2f position, final String data) {
this.document.addElement(new Text(position, Configs.getConfigFonts().getSize(), data, this.paintState.clone())); text(position, Configs.getConfigFonts().getSize(), data);
} }
} }

View File

@ -30,17 +30,23 @@ public class Text extends Base {
public Text(final PaintState parentPaintState) { public Text(final PaintState parentPaintState) {
super(parentPaintState); super(parentPaintState);
} }
public Text(final Vector2f position, final float fontSize, final String decoratedText, final PaintState parentPaintState) { public Text(final Vector2f position, final float fontSize, final String decoratedText, final PaintState parentPaintState) {
super(parentPaintState); super(parentPaintState);
this.position = position; this.position = position;
this.fontSize = fontSize; this.fontSize = fontSize;
this.texts.add(new TextSpan(position, decoratedText, FontProperty.DEFAULT_FONT, parentPaintState.clone())); this.texts.add(new TextSpan(position, decoratedText, FontProperty.DEFAULT_FONT.withSize(fontSize), parentPaintState.clone()));
}
public Text(final Vector2f position, final String fontName,final float fontSize, final String decoratedText, final PaintState parentPaintState) {
super(parentPaintState);
this.position = position;
this.fontSize = fontSize;
this.texts.add(new TextSpan(position, decoratedText, FontProperty.DEFAULT_FONT.withSize(fontSize).withFontName(fontName), parentPaintState.clone()));
} }
@Override @Override
public void display(final int spacing) { public void display(final int spacing) {
Log.debug(spacingDist(spacing) + "Text : "); Log.verbose(spacingDist(spacing) + "Text : ");
for (TextSpan elem : this.texts) { for (TextSpan elem : this.texts) {
Log.debug(spacingDist(spacing + 1) + elem.toString()); Log.debug(spacingDist(spacing + 1) + elem.toString());
} }
@ -48,7 +54,7 @@ public class Text extends Base {
@Override @Override
public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) { public void draw(final Renderer myRenderer, final Matrix2x3f basicTrans, final int level) {
Log.warning(spacingDist(level) + "DRAW esvg::Text ==> position = " + this.position); Log.verbose(spacingDist(level) + "DRAW esvg::Text ==> position = " + this.position);
if (this.texts.size() == 0) { if (this.texts.size() == 0) {
Log.verbose(spacingDist(level + 1) + "No text ..."); Log.verbose(spacingDist(level + 1) + "No text ...");
return; return;
@ -65,19 +71,21 @@ public class Text extends Base {
int realSize = font.calculateFontRealHeight((int) elem.fontState().fontSize()); int realSize = font.calculateFontRealHeight((int) elem.fontState().fontSize());
float scale = realSize / font.getUnitsPerEm(); float scale = realSize / font.getUnitsPerEm();
//Log.warning("elem.fontState() =" + elem.fontState());
//Log.warning("scale =" + scale + " font size = " + elem.fontState().fontSize() + " realSize=" + realSize);
float offsetWriting = 0; float offsetWriting = 0;
int lastValue = 0; int lastValue = 0;
for (char uVal : elem.text().toCharArray()) { for (char uVal : elem.text().toCharArray()) {
Log.warning(spacingDist(level) + " elem.position = " + elem.position()); Log.verbose(spacingDist(level) + " elem.position = " + elem.position());
Glyph glyph = font.getGlyph(uVal); Glyph glyph = font.getGlyph(uVal);
if (glyph == null) { if (glyph == null) {
lastValue = uVal; //lastValue = uVal;
continue; continue;
} }
if (withKerning) { if (withKerning) {
//offsetWriting -= glyph.getKerning(lastValue) * scale; offsetWriting -= glyph.getKerning(lastValue) * scale;
Log.info(" ==> kerning offset = " + (glyph.getKerning(lastValue) * scale)); Log.verbose(" ==> kerning offset = " + (glyph.getKerning(lastValue) * scale));
lastValue = uVal; lastValue = uVal;
} }
@ -85,7 +93,7 @@ public class Text extends Base {
//Matrix2x3f mtx = this.transformMatrix; //Matrix2x3f mtx = this.transformMatrix;
Vector2f tranlate = new Vector2f(elem.position().x() + offsetWriting, elem.position().y() - font.getDescent() * scale); Vector2f tranlate = new Vector2f(elem.position().x() + offsetWriting, elem.position().y() - font.getDescent() * scale);
Log.warning("translate : " + tranlate); Log.verbose("translate : " + tranlate);
Matrix2x3f translateGlyph = Matrix2x3f.createTranslate(tranlate); Matrix2x3f translateGlyph = Matrix2x3f.createTranslate(tranlate);
Matrix2x3f scaleGlyph = Matrix2x3f.createScale(new Vector2f(scale, -scale)); Matrix2x3f scaleGlyph = Matrix2x3f.createScale(new Vector2f(scale, -scale));
@ -132,7 +140,7 @@ public class Text extends Base {
if (this.paint.strokeWidth > 0.0f) { if (this.paint.strokeWidth > 0.0f) {
colorStroke = DynamicColor.createColor(this.paint.stroke, mtx); colorStroke = DynamicColor.createColor(this.paint.stroke, mtx);
if (colorStroke == null) { if (colorStroke == null) {
Log.warning("Color stroke is null: ..."); Log.verbose("Color stroke is null: ...");
} else { } else {
// check if we need to display stroke: // check if we need to display stroke:
SegmentList listSegmentStroke = new SegmentList(); SegmentList listSegmentStroke = new SegmentList();
@ -147,7 +155,7 @@ public class Text extends Base {
myRenderer.print(tmpFill, colorFill, tmpStroke, colorStroke, this.paint.opacity); myRenderer.print(tmpFill, colorFill, tmpStroke, colorStroke, this.paint.opacity);
} }
offsetWriting += advenceXLocal; offsetWriting += advenceXLocal;
Log.error("offset X =" + offsetWriting + " + " + advenceXLocal + " " + uVal); //Log.warning("offset X =" + offsetWriting + " + " + advenceXLocal + " " + uVal);
} }
} }
} }
@ -262,6 +270,19 @@ record FontProperty(
boolean bold, boolean bold,
boolean italic) { boolean italic) {
public static final FontProperty DEFAULT_FONT = new FontProperty("FreeSans", 15, false, false); public static final FontProperty DEFAULT_FONT = new FontProperty("FreeSans", 15, false, false);
public FontProperty withSize(final float fontSize) {
return new FontProperty(this.fontName, fontSize, this.bold, this.italic);
}
public FontProperty withFontName(final String fontName) {
return new FontProperty(fontName, this.fontSize, this.bold, this.italic);
}
public FontProperty withBold(final boolean bold) {
return new FontProperty(this.fontName, this.fontSize, bold, this.italic);
}
public FontProperty withSize(final boolean italic) {
return new FontProperty(this.fontName, this.fontSize, this.bold, italic);
}
} }
record TextSpan( record TextSpan(

View File

@ -1,12 +1,12 @@
package org.atriasoft.esvg.render; package org.atriasoft.esvg.render;
import org.atriasoft.etk.math.Vector2i;
import org.atriasoft.etk.util.Pair;
import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.esvg.EsvgDocument; import org.atriasoft.esvg.EsvgDocument;
import org.atriasoft.esvg.internal.Log; import org.atriasoft.esvg.internal.Log;
import org.atriasoft.etk.Color; import org.atriasoft.etk.Color;
import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.math.Vector2i;
import org.atriasoft.etk.util.Pair;
/** @file /** @file
* @author Edouard DUPIN * @author Edouard DUPIN
@ -21,7 +21,7 @@ public interface DynamicColor {
return null; return null;
} }
if (color.second.isEmpty()) { if (color.second.isEmpty()) {
Log.error("use stroke color :" + color); Log.verbose("use stroke color :" + color);
return new DynamicColorUni(color.first); return new DynamicColorUni(color.first);
} }
return new DynamicColorSpecial(color.second, mtx); return new DynamicColorSpecial(color.second, mtx);

View File

@ -4,9 +4,9 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.atriasoft.esvg.internal.Log; import org.atriasoft.esvg.internal.Log;
import org.atriasoft.etk.util.Pair;
import org.atriasoft.etk.math.Matrix2x3f; import org.atriasoft.etk.math.Matrix2x3f;
import org.atriasoft.etk.math.Vector2f; import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.util.Pair;
public class PointList { public class PointList {
public List<List<Point>> data = new ArrayList<>(); public List<List<Point>> data = new ArrayList<>();
@ -29,9 +29,9 @@ public class PointList {
} }
public void display() { public void display() {
Log.warning(" Display list of points : size=" + this.data.size()); Log.verbose(" Display list of points : size=" + this.data.size());
for (List<Point> it : this.data) { for (List<Point> it : this.data) {
Log.warning(" Find List " + it.size() + " members"); Log.verbose(" Find List " + it.size() + " members");
for (int iii = 0; iii < it.size(); ++iii) { for (int iii = 0; iii < it.size(); ++iii) {
Point elem = it.get(iii); Point elem = it.get(iii);
Log.verbose(" [" + iii + "] Find " + elem.type + " " + elem.pos); Log.verbose(" [" + iii + "] Find " + elem.type + " " + elem.pos);