diff --git a/.classpath b/.classpath index 521c6bb..46b460e 100644 --- a/.classpath +++ b/.classpath @@ -48,11 +48,6 @@ - - - - - diff --git a/src/module-info.java b/src/module-info.java index 6ee81df..eaea52f 100644 --- a/src/module-info.java +++ b/src/module-info.java @@ -4,7 +4,21 @@ open module org.atriasoft.ewol { exports org.atriasoft.ewol; + exports org.atriasoft.ewol.annotation; + exports org.atriasoft.ewol.compositing; + exports org.atriasoft.ewol.compositing.tools; + exports org.atriasoft.ewol.context; + exports org.atriasoft.ewol.event; + exports org.atriasoft.ewol.object; + exports org.atriasoft.ewol.resource; + exports org.atriasoft.ewol.resource.font; + exports org.atriasoft.ewol.tools; + exports org.atriasoft.ewol.widget; + exports org.atriasoft.ewol.widget.meta; + + exports org.atriasoft.echrono; exports org.atriasoft.egami; + exports org.atriasoft.esignal; requires transitive org.atriasoft.gale; requires transitive org.atriasoft.etk; diff --git a/src/org/atriasoft/ewol/DrawProperty.java b/src/org/atriasoft/ewol/DrawProperty.java index 57a074b..5a44339 100644 --- a/src/org/atriasoft/ewol/DrawProperty.java +++ b/src/org/atriasoft/ewol/DrawProperty.java @@ -63,6 +63,6 @@ public class DrawProperty { @Override public String toString() { - return "DrawProperty [windowsSize=" + this.windowsSize + ", start=" + this.origin + ", stop=" + this.origin.addNew(this.size) + "]"; + return "DrawProperty [windowsSize=" + this.windowsSize + ", start=" + this.origin + ", stop=" + this.origin.add(this.size) + "]"; } } diff --git a/src/org/atriasoft/ewol/compositing/Compositing.java b/src/org/atriasoft/ewol/compositing/Compositing.java index f999a25..d71b048 100644 --- a/src/org/atriasoft/ewol/compositing/Compositing.java +++ b/src/org/atriasoft/ewol/compositing/Compositing.java @@ -1,3 +1,5 @@ +package org.atriasoft.ewol.compositing; + import org.atriasoft.etk.math.Matrix4f; import org.atriasoft.etk.math.Vector3f; diff --git a/src/org/atriasoft/ewol/compositing/CompositingImage.java b/src/org/atriasoft/ewol/compositing/CompositingImage.java index c63ad00..79ba904 100644 --- a/src/org/atriasoft/ewol/compositing/CompositingImage.java +++ b/src/org/atriasoft/ewol/compositing/CompositingImage.java @@ -8,6 +8,7 @@ package org.atriasoft.ewol.compositing; import org.atriasoft.egami.Image; import org.atriasoft.etk.Color; import org.atriasoft.etk.Uri; +import org.atriasoft.etk.math.FMath; import org.atriasoft.etk.math.Matrix4f; import org.atriasoft.etk.math.Vector2f; import org.atriasoft.etk.math.Vector2i; @@ -116,7 +117,7 @@ class CompositingImage extends Compositing { OpenGL.enable(OpenGL.Flag.flag_depthTest); } // set Matrix : translation/positionMatrix - final Matrix4f tmpMatrix = OpenGL.getMatrix().multiplyNew(this.matrixApply); + final Matrix4f tmpMatrix = OpenGL.getMatrix().multiply(this.matrixApply); this.GLprogram.use(); this.GLprogram.uniformMatrix(this.GLMatrix, tmpMatrix); // TextureID @@ -197,7 +198,7 @@ class CompositingImage extends Compositing { * @param[in] _size size of the output image */ public void print(final Vector2i _size) { - print(new Vector2f(_size.x, _size.y)); + print(new Vector2f(_size.x(), _size.y())); }; /** @@ -210,40 +211,36 @@ class CompositingImage extends Compositing { if (this.resource == null) { return; } - final Vector2f openGLSize = new Vector2f(this.resource.getOpenGlSize().x, this.resource.getOpenGlSize().y); + final Vector2f openGLSize = new Vector2f(this.resource.getOpenGlSize().x(), this.resource.getOpenGlSize().y()); final Vector2i usefullSize = this.resource.getUsableSize(); - final Vector2f ratio = new Vector2f(usefullSize.x / openGLSize.x, usefullSize.y / openGLSize.y); - final Vector2f sourcePosStart = _sourcePosStart.multiplyNew(ratio); - final Vector2f sourcePosStop = _sourcePosStop.multiplyNew(ratio); + final Vector2f ratio = new Vector2f(usefullSize.x() / openGLSize.x(), usefullSize.y() / openGLSize.y()); + final Vector2f sourcePosStart = _sourcePosStart.multiply(ratio); + final Vector2f sourcePosStop = _sourcePosStop.multiply(ratio); Log.verbose(" openGLSize=" + openGLSize + " usableSize=" + usefullSize + " start=" + sourcePosStart + " stop=" + sourcePosStop); if (this.angle == 0.0f) { - Vector3f point = this.position.clone(); + Vector3f point = this.position; final Vector3f[] coords = new Vector3f[6]; final Vector2f[] coordsTex = new Vector2f[6]; final Color[] colors = new Color[6]; int indexElem = 0; - Vector2f tex = new Vector2f(sourcePosStart.x, sourcePosStop.y); + Vector2f tex = new Vector2f(sourcePosStart.x(), sourcePosStop.y()); coords[indexElem] = point; coordsTex[indexElem] = tex; colors[indexElem] = this.color; indexElem++; - tex = new Vector2f(sourcePosStop.x, sourcePosStop.y); - point = point.clone(); - point.setX(this.position.x + _size.x); - point.setY(this.position.y); + tex = new Vector2f(sourcePosStop.x(), sourcePosStop.y()); + point = new Vector3f(this.position.x() + _size.x(), this.position.y(), 0); coords[indexElem] = point; coordsTex[indexElem] = tex; colors[indexElem] = this.color; indexElem++; - tex = new Vector2f(sourcePosStop.x, sourcePosStart.y); - point = point.clone(); - point.setX(this.position.x + _size.x); - point.setY(this.position.y + _size.y); + tex = new Vector2f(sourcePosStop.x(), sourcePosStart.y()); + point = new Vector3f(this.position.x() + _size.x(), this.position.y() + _size.y(), 0); coords[indexElem] = point; coordsTex[indexElem] = tex; colors[indexElem] = this.color; @@ -254,19 +251,15 @@ class CompositingImage extends Compositing { colors[indexElem] = this.color; indexElem++; - tex = new Vector2f(sourcePosStart.x, sourcePosStart.y); - point = point.clone(); - point.setX(this.position.x); - point.setY(this.position.y + _size.y); + tex = new Vector2f(sourcePosStart.x(), sourcePosStart.y()); + point = new Vector3f(this.position.x(), this.position.y() + _size.y(), 0); coords[indexElem] = point; coordsTex[indexElem] = tex; colors[indexElem] = this.color; indexElem++; - tex = new Vector2f(sourcePosStart.x, sourcePosStop.y); - point = point.clone(); - point.setX(this.position.x); - point.setY(this.position.y); + tex = new Vector2f(sourcePosStart.x(), sourcePosStop.y()); + point = new Vector3f(this.position.x(), this.position.y(), 0); coords[indexElem] = point; coordsTex[indexElem] = tex; colors[indexElem] = this.color; @@ -280,36 +273,36 @@ class CompositingImage extends Compositing { return; } - final Vector3f center = this.position.addNew(new Vector3f(_size.x, _size.y, 0)).divide(2.0f); + final Vector3f center = this.position.add(new Vector3f(_size.x(), _size.y(), 0)).divide(2.0f); - final Vector3f limitedSize = new Vector3f(_size.x * 0.5f, _size.y * 0.5f, 0.0f); + final Vector3f limitedSize = new Vector3f(_size.x() * 0.5f, _size.y() * 0.5f, 0.0f); Vector3f point = new Vector3f(0, 0, 0); - Vector2f tex = new Vector2f(_sourcePosStart.x, sourcePosStop.y); + Vector2f tex = new Vector2f(_sourcePosStart.x(), sourcePosStop.y()); final Vector3f[] coords = new Vector3f[6]; final Vector2f[] coordsTex = new Vector2f[6]; final Color[] colors = new Color[6]; int indexElem = 0; - point = new Vector3f(-limitedSize.x, -limitedSize.y, 0); + point = new Vector3f(-limitedSize.x(), -limitedSize.y(), 0); point = point.rotateNew(new Vector3f(0, 0, 1), this.angle).add(center); coords[indexElem] = point; coordsTex[indexElem] = tex; colors[indexElem] = this.color; indexElem++; - tex = new Vector2f(sourcePosStop.x, sourcePosStop.y); - point = new Vector3f(limitedSize.x, -limitedSize.y, 0); + tex = new Vector2f(sourcePosStop.x(), sourcePosStop.y()); + point = new Vector3f(limitedSize.x(), -limitedSize.y(), 0); point = point.rotateNew(new Vector3f(0, 0, 1), this.angle).add(center); coords[indexElem] = point; coordsTex[indexElem] = tex; colors[indexElem] = this.color; indexElem++; - tex = new Vector2f(sourcePosStop.x, sourcePosStart.y); - point = new Vector3f(limitedSize.x, limitedSize.y, 0); + tex = new Vector2f(sourcePosStop.x(), sourcePosStart.y()); + point = new Vector3f(limitedSize.x(), limitedSize.y(), 0); point = point.rotateNew(new Vector3f(0, 0, 1), this.angle).add(center); coords[indexElem] = point; coordsTex[indexElem] = tex; @@ -321,16 +314,16 @@ class CompositingImage extends Compositing { colors[indexElem] = this.color; indexElem++; - tex = new Vector2f(sourcePosStart.x, sourcePosStart.y); - point = new Vector3f(-limitedSize.x, limitedSize.y, 0); + tex = new Vector2f(sourcePosStart.x(), sourcePosStart.y()); + point = new Vector3f(-limitedSize.x(), limitedSize.y(), 0); point = point.rotateNew(new Vector3f(0, 0, 1), this.angle).add(center); coords[indexElem] = point; coordsTex[indexElem] = tex; colors[indexElem] = this.color; indexElem++; - tex = new Vector2f(sourcePosStart.x, sourcePosStop.y); - point = new Vector3f(-limitedSize.x, -limitedSize.y, 0); + tex = new Vector2f(sourcePosStart.x(), sourcePosStop.y()); + point = new Vector3f(-limitedSize.x(), -limitedSize.y(), 0); point = point.rotateNew(new Vector3f(0, 0, 1), this.angle).add(center); coords[indexElem] = point; coordsTex[indexElem] = tex; @@ -353,7 +346,7 @@ class CompositingImage extends Compositing { }; void setClipping(final Vector2f _pos, final Vector2f _posEnd) { - setClipping(new Vector3f(_pos.x, _pos.y, 0), new Vector3f(_posEnd.x, _posEnd.y, 0)); + setClipping(new Vector3f(_pos.x(), _pos.y(), 0), new Vector3f(_posEnd.x(), _posEnd.y(), 0)); }; /** @@ -362,28 +355,8 @@ class CompositingImage extends Compositing { * @param[in] _posEnd End position of the clipping */ public void setClipping(final Vector3f _pos, final Vector3f _posEnd) { - // note the internal system all time request to have a bounding all time in the same order - if (_pos.x <= _posEnd.x) { - this.clippingPosStart.setX(_pos.x); - this.clippingPosStop.setX(_posEnd.x); - } else { - this.clippingPosStart.setX(_posEnd.x); - this.clippingPosStop.setX(_pos.x); - } - if (_pos.y <= _posEnd.y) { - this.clippingPosStart.setY(_pos.y); - this.clippingPosStop.setY(_posEnd.y); - } else { - this.clippingPosStart.setY(_posEnd.y); - this.clippingPosStop.setY(_pos.y); - } - if (_pos.z <= _posEnd.z) { - this.clippingPosStart.setZ(_pos.z); - this.clippingPosStop.setZ(_posEnd.z); - } else { - this.clippingPosStart.setZ(_posEnd.z); - this.clippingPosStop.setZ(_pos.z); - } + this.clippingPosStart = FMath.min(_pos, _posEnd); + this.clippingPosStop = FMath.max(_pos, _posEnd); this.clippingEnable = true; } @@ -396,7 +369,7 @@ class CompositingImage extends Compositing { }; public void setClippingWidth(final Vector2f _pos, final Vector2f _width) { - setClippingWidth(new Vector3f(_pos.x, _pos.y, 0), new Vector3f(_width.x, _width.y, 0)); + setClippingWidth(new Vector3f(_pos.x(), _pos.y(), 0), new Vector3f(_width.x(), _width.y(), 0)); }; /** @@ -405,7 +378,7 @@ class CompositingImage extends Compositing { * @param[in] _width Width size of the clipping */ public void setClippingWidth(final Vector3f _pos, final Vector3f _width) { - setClipping(_pos, _pos.addNew(_width)); + setClipping(_pos, _pos.add(_width)); } /** @@ -417,7 +390,7 @@ class CompositingImage extends Compositing { }; public void setPos(final Vector2f _pos) { - setPos(new Vector3f(_pos.x, _pos.y, 0)); + setPos(new Vector3f(_pos.x(), _pos.y(), 0)); } /** @@ -429,7 +402,7 @@ class CompositingImage extends Compositing { } public void setRelPos(final Vector2f _pos) { - setRelPos(new Vector3f(_pos.x, _pos.y, 0)); + setRelPos(new Vector3f(_pos.x(), _pos.y(), 0)); } /** @@ -463,7 +436,7 @@ class CompositingImage extends Compositing { public void setSource(final Uri _uri, final Vector2i _size) { clear(); - if (this.filename == _uri && this.requestSize.x == _size.x && this.requestSize.y == _size.y) { + if (this.filename == _uri && this.requestSize.x() == _size.x() && this.requestSize.y() == _size.y()) { // Nothing to do ... return; } @@ -474,7 +447,7 @@ class CompositingImage extends Compositing { this.resource = null; this.resourceImage = null; - final Vector2i tmpSize = new Vector2i(_size.x, _size.y); + final Vector2i tmpSize = new Vector2i(_size.x(), _size.y()); // note that no image can be loaded... if (_uri.isEmpty() == false) { // link to new one diff --git a/src/org/atriasoft/ewol/compositing/Drawing.java b/src/org/atriasoft/ewol/compositing/Drawing.java new file mode 100644 index 0000000..01754f2 --- /dev/null +++ b/src/org/atriasoft/ewol/compositing/Drawing.java @@ -0,0 +1,526 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ +package org.atriasoft.ewol.compositing; + +import java.util.ArrayList; +import java.util.List; + +import org.atriasoft.etk.Color; +import org.atriasoft.etk.Uri; +import org.atriasoft.etk.math.FMath; +import org.atriasoft.etk.math.Matrix4f; +import org.atriasoft.etk.math.Vector2f; +import org.atriasoft.etk.math.Vector3f; +import org.atriasoft.ewol.internal.Log; +import org.atriasoft.gale.backend3d.OpenGL; +import org.atriasoft.gale.resource.ResourceProgram; +import org.atriasoft.gale.resource.ResourceVirtualBufferObject; + +class Drawing extends Compositing { + + protected static int vboIdCoord = 0; + protected static int vboIdColor = 1; + private Vector3f position = new Vector3f(0, 0, 0); // !< The current position to draw + private Vector3f clippingPosStart = new Vector3f(0, 0, 0); // !< Clipping start position + private Vector3f clippingPosStop = new Vector3f(0, 0, 0); // !< Clipping stop position + private boolean clippingEnable = false; // !< true if the clipping must be activated + private Color color = Color.BLACK; // !< The text foreground color + private Color colorBg = Color.NONE; // !< The text background color + private ResourceProgram GLprogram; // !< pointer on the opengl display program + private int GLPosition = -1; // !< openGL id on the element (vertex buffer) + private int GLMatrix = -1; // !< openGL id on the element (transformation matrix) + private int GLMatrixPosition = -1; // !< position matrix + private int GLColor = -1; // !< openGL id on the element (color buffer) + protected ResourceVirtualBufferObject VBO; + + private float thickness = 0; // !< when drawing line and other things + + private int triElement = 0; // !< special counter of the single dot generated + + private final Vector3f[] triangle = new Vector3f[3]; // !< Register every system with a combinaison of tiangle + + private final Color[] tricolor = new Color[3]; // !< Register every the associated color foreground + private final List outTriangles = new ArrayList<>(); + private final List outColors = new ArrayList<>(); + + // internal API for the generation abstraction of triangles + /** + * @brief Basic ructor + */ + public Drawing() { + loadProgram(); + for (int iii = 0; iii < 3; iii++) { + this.triangle[iii] = this.position; + this.tricolor[iii] = this.color; + } + // Create the VBO: + this.VBO = ResourceVirtualBufferObject.create(4); + if (this.VBO == null) { + Log.error("can not instanciate VBO ..."); + return; + } + // TO facilitate some debugs we add a name of the VBO: + this.VBO.setName("[VBO] of ewol::compositing::Area"); + } + + /** + * @brief add a point reference at the current position (this is a vertex + * reference at the current position + */ + public void addVertex() { + internalSetColor(this.color); + setPoint(this.position); + } + + /** + * @brief draw a 2D circle with the specify rafdius parameter. + * @param[in] _radius Distence to the dorder + * @param[in] _angleStart start angle of this circle ([0..2PI] otherwithe == > + * disable) + * @param[in] _angleStop stop angle of this circle ([0..2PI] otherwithe == > + * disable) + */ + public void circle(final float _radius) { + circle(_radius, 0); + } + + public void circle(final float _radius, final float _angleStart) { + circle(_radius, _angleStart, 2.0f * FMath.PI); + }; + + public void circle(float _radius, final float _angleStart, float _angleStop) { + resetCount(); + + if (_radius < 0) { + _radius *= -1; + } + _angleStop = _angleStop - _angleStart; + + int nbOcurence = (int) _radius; + if (nbOcurence < 10) { + nbOcurence = 10; + } + + // display background : + if (this.colorBg.a() != 0) { + internalSetColor(this.colorBg); + for (int iii = 0; iii < nbOcurence; iii++) { + setPoint(new Vector3f(this.position.x(), this.position.y(), 0)); + + float angleOne = _angleStart + (_angleStop * iii / nbOcurence); + float offsety = FMath.sin(angleOne) * _radius; + float offsetx = FMath.cos(angleOne) * _radius; + + setPoint(new Vector3f(this.position.x() + offsetx, this.position.y() + offsety, 0)); + + float angleTwo = _angleStart + (_angleStop * (iii + 1) / nbOcurence); + offsety = FMath.sin(angleTwo) * _radius; + offsetx = FMath.cos(angleTwo) * _radius; + + setPoint(new Vector3f(this.position.x() + offsetx, this.position.y() + offsety, 0)); + } + } + + // show if we have a border : + if (this.thickness == 0 || this.color.a() == 0) { + return; + } + internalSetColor(this.color); + for (int iii = 0; iii < nbOcurence; iii++) { + + float angleOne = _angleStart + (_angleStop * iii / nbOcurence); + float offsetExty = FMath.sin(angleOne) * (_radius + this.thickness / 2); + float offsetExtx = FMath.cos(angleOne) * (_radius + this.thickness / 2); + float offsetInty = FMath.sin(angleOne) * (_radius - this.thickness / 2); + float offsetIntx = FMath.cos(angleOne) * (_radius - this.thickness / 2); + + float angleTwo = _angleStart + (_angleStop * (iii + 1) / nbOcurence); + float offsetExt2y = FMath.sin(angleTwo) * (_radius + this.thickness / 2); + float offsetExt2x = FMath.cos(angleTwo) * (_radius + this.thickness / 2); + float offsetInt2y = FMath.sin(angleTwo) * (_radius - this.thickness / 2); + float offsetInt2x = FMath.cos(angleTwo) * (_radius - this.thickness / 2); + + setPoint(new Vector3f(this.position.x() + offsetIntx, this.position.y() + offsetInty, 0)); + setPoint(new Vector3f(this.position.x() + offsetExtx, this.position.y() + offsetExty, 0)); + setPoint(new Vector3f(this.position.x() + offsetExt2x, this.position.y() + offsetExt2y, 0)); + + setPoint(new Vector3f(this.position.x() + offsetExt2x, this.position.y() + offsetExt2y, 0)); + setPoint(new Vector3f(this.position.x() + offsetInt2x, this.position.y() + offsetInt2y, 0)); + setPoint(new Vector3f(this.position.x() + offsetIntx, this.position.y() + offsetInty, 0)); + } + } + + /** + * @brief clear alll tre registered element in the current element + */ + @Override + public void clear() { + // call upper class + super.clear(); + // reset Buffer : + this.VBO.clear(); + this.outTriangles.clear(); + this.outColors.clear(); + + // reset temporal variables : + this.position = Vector3f.ZERO; + + this.clippingPosStart = Vector3f.ZERO; + this.clippingPosStop = Vector3f.ZERO; + this.clippingEnable = false; + + this.color = Color.BLACK; + this.colorBg = Color.NONE; + + for (int iii = 0; iii < 3; iii++) { + this.triangle[iii] = this.position; + this.tricolor[iii] = this.color; + } + } + + /** + * @brief draw All the refistered text in the current element on openGL + */ + @Override + public void draw(final boolean _disableDepthTest) { + + // push data on the VBO + // TODO optimize this with single push when needed + this.VBO.setVboData(Drawing.vboIdCoord, this.outTriangles.toArray(Vector3f[]::new)); + this.VBO.setVboData(Drawing.vboIdColor, this.outColors.toArray(Color[]::new)); + this.VBO.flush(); + + if (this.GLprogram == null) { + Log.error("No shader ..."); + return; + } + // set Matrix : translation/positionMatrix + Matrix4f tmpMatrix = OpenGL.getMatrix().multiplyNew(this.matrixApply); + this.GLprogram.use(); + this.GLprogram.uniformMatrix(this.GLMatrix, tmpMatrix); + this.GLprogram.uniformMatrix(this.GLMatrixPosition, Matrix4f.identity()); + // position: + this.GLprogram.sendAttributePointer(this.GLPosition, this.VBO, Drawing.vboIdCoord); + // color: + this.GLprogram.sendAttributePointer(this.GLColor, this.VBO, Drawing.vboIdColor); + // Request the draw od the elements : + OpenGL.drawArrays(OpenGL.RenderMode.triangle, 0, this.VBO.bufferSize(Drawing.vboIdCoord)); + this.GLprogram.unUse(); + } + + /** + * @brief Lunch the generation of triangle + */ + private void generateTriangle() { + this.triElement = 0; + this.outTriangles.add(this.triangle[0]); + this.outTriangles.add(this.triangle[1]); + this.outTriangles.add(this.triangle[2]); + this.outColors.add(this.tricolor[0]); + this.outColors.add(this.tricolor[1]); + this.outColors.add(this.tricolor[2]); + } + + /** + * @brief Get the foreground color of the font. + * @return Foreground color. + */ + public Color getColor() { + return this.color; + } + + /** + * @brief Get the background color of the font. + * @return Background color. + */ + public Color getColorBg() { + return this.colorBg; + }; + + /** + * @brief get the current display position (sometime needed in the gui control) + * @return the current position. + */ + public Vector3f getPos() { + return this.position; + }; + + /** + * @brief set the Color of the current triangle drawing + * @param[in] _color Color to current dots generated + */ + private void internalSetColor(final Color _color) { + if (this.triElement < 1) { + this.tricolor[0] = _color; + } + if (this.triElement < 2) { + this.tricolor[1] = _color; + } + if (this.triElement < 3) { + this.tricolor[2] = _color; + } + }; + + public void lineRel(final Vector2f _vect) { + lineRel(new Vector3f(_vect.x(), _vect.y(), 0)); + }; + + /** + * @brief Relative drawing a line (spacial vector) + * @param[in] _vect Vector of the curent line. + */ + public void lineRel(final Vector3f _vect) { + lineTo(this.position.add(_vect)); + }; + + public void lineTo(final Vector2f _dest) { + lineTo(new Vector3f(_dest.x(), _dest.y(), 0)); + }; + + /** + * @brief draw a line to a specific position + * @param[in] _dest Position of the end of the line. + */ + public void lineTo(final Vector3f _dest) { + resetCount(); + internalSetColor(this.color); + // Log.verbose("DrawLine : " + this.position + " to " + _dest); + if (this.position.x() == _dest.x() && this.position.y() == _dest.y() && this.position.z() == _dest.z()) { + // Log.warning("Try to draw a line width 0"); + return; + } + // teta = tan-1(oposer/adjacent) + float teta = 0; + if (this.position.x() <= _dest.x()) { + teta = FMath.atan((_dest.y() - this.position.y()) / (_dest.x() - this.position.x())); + } else { + teta = FMath.PI + FMath.atan((_dest.y() - this.position.y())) / (_dest.x() - this.position.x()); + } + if (teta < 0) { + teta += 2 * FMath.PI; + } else if (teta > 2 * FMath.PI) { + teta -= 2 * FMath.PI; + } + // Log.debug("teta = " + (teta*180/(FMath.PI)) + " deg." ); + float offsety = FMath.sin(teta - FMath.PI / 2) * (this.thickness / 2); + float offsetx = FMath.cos(teta - FMath.PI / 2) * (this.thickness / 2); + setPoint(new Vector3f(this.position.x() - offsetx, this.position.y() - offsety, this.position.z())); + setPoint(new Vector3f(this.position.x() + offsetx, this.position.y() + offsety, this.position.z())); + setPoint(new Vector3f(_dest.x() + offsetx, _dest.y() + offsety, this.position.z())); + + setPoint(new Vector3f(_dest.x() + offsetx, _dest.y() + offsety, _dest.z())); + setPoint(new Vector3f(_dest.x() - offsetx, _dest.y() - offsety, _dest.z())); + setPoint(new Vector3f(this.position.x() - offsetx, this.position.y() - offsety, _dest.z())); + // update the system position : + this.position = _dest; + }; + + /** + * @brief load the openGL program and get all the ID needed + */ + private void loadProgram() { + // remove previous loading ... in case + unLoadProgram(); + // oad the new ... + this.GLprogram = ResourceProgram.create(new Uri("DATA", "color3.vert", "ewol"), + new Uri("DATA", "color3.frag", "ewol")); + // get the shader resource : + if (this.GLprogram != null) { + this.GLPosition = this.GLprogram.getAttribute("EW_coord3d"); + this.GLColor = this.GLprogram.getAttribute("EW_color"); + this.GLMatrix = this.GLprogram.getUniform("EW_MatrixTransformation"); + this.GLMatrixPosition = this.GLprogram.getUniform("EW_MatrixPosition"); + } + }; + + public void rectangle(final Vector2f _dest) { + rectangle(new Vector3f(_dest.x(), _dest.y(), 0)); + }; + + /** + * @brief draw a 2D rectangle to the position requested. + * @param[in] _dest Position the the end of the rectangle + */ + public void rectangle(final Vector3f _dest) { + resetCount(); + internalSetColor(this.color); + /* + * Bitmap position xA xB yC *------* | | | | yD *------* + */ + float dxA = this.position.x(); + float dxB = _dest.x(); + if (dxA > dxB) { + // inverse order : + float tmp = dxA; + dxA = dxB; + dxB = tmp; + } + float dyC = this.position.y(); + float dyD = _dest.y(); + if (dyC > dyD) { + // inverse order : + float tmp = dyC; + dyC = dyD; + dyD = tmp; + } + if (true == this.clippingEnable) { + if (dxA < this.clippingPosStart.x()) { + dxA = this.clippingPosStart.x(); + } + if (dxB > this.clippingPosStop.x()) { + dxB = this.clippingPosStop.x(); + } + if (dyC < this.clippingPosStart.y()) { + dyC = this.clippingPosStart.y(); + } + if (dyD > this.clippingPosStop.y()) { + dyD = this.clippingPosStop.y(); + } + } + if (dyC >= dyD || dxA >= dxB) { + return; + } + setPoint(new Vector3f(dxA, dyD, 0)); + setPoint(new Vector3f(dxA, dyC, 0)); + setPoint(new Vector3f(dxB, dyC, 0)); + + setPoint(new Vector3f(dxB, dyC, 0)); + setPoint(new Vector3f(dxB, dyD, 0)); + setPoint(new Vector3f(dxA, dyD, 0)); + }; + + public void rectangleWidth(final Vector2f _size) { + rectangleWidth(new Vector3f(_size.x(), _size.y(), 0)); + }; + + /** + * @brief draw a 2D rectangle to the requested size. + * @param[in] _size size of the rectangle + */ + public void rectangleWidth(final Vector3f _size) { + rectangle(this.position.add(_size)); + } + + /** + * @brief in case of some error the count can be reset + */ + private void resetCount() { + this.triElement = 0; + }; + + public void setClipping(final Vector2f _pos, final Vector2f _posEnd) { + setClipping(new Vector3f(_pos.x(), _pos.y(), -1), new Vector3f(_posEnd.x(), _posEnd.y(), 1)); + }; + + /** + * @brief Request a clipping area for the text (next draw only) + * @param[in] _pos Start position of the clipping + * @param[in] _posEnd End position of the clipping + */ + public void setClipping(final Vector3f _pos, final Vector3f _posEnd) { + // note the internal system all time request to have a bounding all time in the + // same order + this.clippingPosStop = Vector3f.max(_pos, _posEnd); + this.clippingPosStart = Vector3f.min(_pos, _posEnd); + this.clippingEnable = true; + } + + /** + * @brief enable/Disable the clipping (without lose the current clipping + * position) + * @brief _newMode The new status of the clipping + */ + public void setClippingMode(final boolean _newMode) { + this.clippingEnable = _newMode; + } + + public void setClippingWidth(final Vector2f _pos, final Vector2f _width) { + setClippingWidth(new Vector3f(_pos.x(), _pos.y(), -1), new Vector3f(_width.x(), _width.y(), 2)); + } + + /** + * @brief Request a clipping area for the text (next draw only) + * @param[in]_ pos Start position of the clipping + * @param[in] _width Width size of the clipping + */ + public void setClippingWidth(final Vector3f _pos, final Vector3f _width) { + setClipping(_pos, _pos.add(_width)); + }; + + /** + * @brief set the Color of the current foreground font + * @param[in] _color Color to set on foreground (for next print) + */ + public void setColor(final Color _color) { + this.color = _color; + }; + + /** + * @brief set the background color of the font (for selected Text (not the + * global BG)) + * @param[in] _color Color to set on background (for next print) + */ + public void setColorBg(final Color _color) { + this.colorBg = _color; + }; + + /** + * @brief internal add of the specific point + * @param[in] _point The requeste dpoint to add + */ + private void setPoint(final Vector3f point) { + this.triangle[this.triElement] = point; + this.triElement++; + if (this.triElement >= 3) { + generateTriangle(); + } + this.VBO.flush(); + } + + public void setPos(final Vector2f _pos) { + setPos(new Vector3f(_pos.x(), _pos.y(), 0)); + }; + + /** + * @brief set position for the next text writen + * @param[in] _pos Position of the text (in 3D) + */ + public void setPos(final Vector3f _pos) { + this.position = _pos; + }; + + public void setRelPos(final Vector2f _pos) { + setRelPos(new Vector3f(_pos.x(), _pos.y(), 0)); + } + + /** + * @brief set relative position for the next text writen + * @param[in] _pos ofset apply of the text (in 3D) + */ + public void setRelPos(final Vector3f _pos) { + this.position = this.position.add(_pos); + } + + /** + * @brief Specify the line thickness for the next elements + * @param[in] _thickness The thickness disired for the next print + */ + public void setThickness(final float _thickness) { + this.thickness = _thickness; + // thickness must be positive + if (this.thickness < 0) { + this.thickness *= -1; + } + } + + /** + * @brief Un-Load the openGL program and get all the ID needed + */ + private void unLoadProgram() { + this.GLprogram = null; + } + +} \ No newline at end of file diff --git a/src/org/atriasoft/ewol/compositing/Text.cpp b/src/org/atriasoft/ewol/compositing/Text.cpp deleted file mode 100644 index 611a2ae..0000000 --- a/src/org/atriasoft/ewol/compositing/Text.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/** @file - * @author Edouard DUPIN - * @copyright 2011, Edouard DUPIN, all right reserved - * @license MPL v2.0 (see license file) - */ - -#include -#include -#include -#include - -#include -ETK_DECLARE_TYPE(ewol::compositing::Text); - -ewol::compositing::Text::Text( String _fontName, int _fontSize) : - this.font(null) { - setFont(_fontName, _fontSize); -} - -ewol::compositing::Text::~Text() { - -} - -void ewol::compositing::Text::drawMT( Matrix4f _transformationMatrix, boolean _enableDepthTest) { - - // draw BG in any case: - this.vectorialDraw.draw(); - - if ( this.VBO.bufferSize(this.vboIdCoord) <= 0 - || this.font == null) { - // TODO : set it back ... - //Log.warning("Nothink to draw..."); - return; - } - if (this.font == null) { - Log.warning("no font..."); - return; - } - if (this.GLprogram == null) { - Log.error("No shader ..."); - return; - } - if (_enableDepthTest == true) { - gale::openGL::enable(gale::openGL::flag_depthTest); - } - // set Matrix : translation/positionMatrix - Matrix4f projMatrix = gale::openGL::getMatrix(); - Matrix4f camMatrix = gale::openGL::getCameraMatrix(); - Matrix4f tmpMatrix = projMatrix * camMatrix * _transformationMatrix; - this.GLprogram.use(); - this.GLprogram.uniformMatrix(this.GLMatrix, tmpMatrix); - // Texture: - this.GLprogram.setTexture0(this.GLtexID, this.font.getRendererId()); - this.GLprogram.uniform1i(this.GLtextWidth, this.font.getOpenGlSize().x()); - this.GLprogram.uniform1i(this.GLtextHeight, this.font.getOpenGlSize().x()); - // position: - this.GLprogram.sendAttributePointer(this.GLPosition, this.VBO, this.vboIdCoord); - // Texture: - this.GLprogram.sendAttributePointer(this.GLtexture, this.VBO, this.vboIdCoordText); - // color: - this.GLprogram.sendAttributePointer(this.GLColor, this.VBO, this.vboIdColor); - // Request the draw od the elements: - gale::openGL::drawArrays(gale::openGL::renderMode::triangle, 0, this.VBO.bufferSize(this.vboIdCoord)); - this.GLprogram.unUse(); - if (_enableDepthTest == true) { - gale::openGL::disable(gale::openGL::flag_depthTest); - } -} - -void ewol::compositing::Text::drawD(boolean _disableDepthTest) { - // draw BG in any case: - this.vectorialDraw.draw(_disableDepthTest); - - if ( this.VBO.bufferSize(this.vboIdCoord) <= 0 - || this.font == null) { - //Log.warning("Nothink to draw..."); - return; - } - if (this.font == null) { - Log.warning("no font..."); - return; - } - if (this.GLprogram == null) { - Log.error("No shader ..."); - return; - } - // set Matrix : translation/positionMatrix - Matrix4f tmpMatrix = gale::openGL::getMatrix()*this.matrixApply; - this.GLprogram.use(); - this.GLprogram.uniformMatrix(this.GLMatrix, tmpMatrix); - // Texture : - this.GLprogram.setTexture0(this.GLtexID, this.font.getRendererId()); - this.GLprogram.uniform1i(this.GLtextWidth, this.font.getOpenGlSize().x()); - this.GLprogram.uniform1i(this.GLtextHeight, this.font.getOpenGlSize().x()); - // position: - this.GLprogram.sendAttributePointer(this.GLPosition, this.VBO, this.vboIdCoord); - // Texture: - this.GLprogram.sendAttributePointer(this.GLtexture, this.VBO, this.vboIdCoordText); - // color: - this.GLprogram.sendAttributePointer(this.GLColor, this.VBO, this.vboIdColor); - // Request the draw od the elements : - gale::openGL::drawArrays(gale::openGL::renderMode::triangle, 0, this.VBO.bufferSize(this.vboIdCoord)); - this.GLprogram.unUse(); -} - -float ewol::compositing::Text::getSize() { - if (this.font == null) { - Log.warning("no font..."); - return 1.0f; - } - return this.font.getFontSize(); -} -float ewol::compositing::Text::getHeight() { - if (this.font == null) { - Log.warning("no font..."); - return 10.0f; - } - return this.font.getHeight(this.mode); -} -ewol::GlyphProperty * ewol::compositing::Text::getGlyphPointer(Character _charcode) { - if (this.font == null) { - Log.warning("no font..."); - return null; - } - return this.font.getGlyphPointer(_charcode, this.mode); -} - -void ewol::compositing::Text::setFontSize(int _fontSize) { - // get old size - String fontName = ""; - if (this.font != null) { - fontName = this.font.getName(); - // Remove the :XX for the size ... - int pos = fontName.rfind(':'); - fontName.erase(pos, fontName.size()-pos); - } - setFont(fontName, _fontSize); -} - -void ewol::compositing::Text::setFontName( String _fontName) { - // get old size - int fontSize = -1; - if (this.font != null) { - fontSize = this.font.getFontSize(); - } - setFont(_fontName, fontSize); -} - -void ewol::compositing::Text::setFont(String _fontName, int _fontSize) { - clear(); - // remove old one - ememory::Ptr previousFont = this.font; - if (_fontSize <= 0) { - _fontSize = ewol::getContext().getFontDefault().getSize(); - } - if (_fontName == "") { - _fontName = ewol::getContext().getFontDefault().getName(); - } - _fontName += ":"; - _fontName += etk::toString(_fontSize); - Log.verbose("plop : " + _fontName + " size=" + _fontSize + " result :" + _fontName); - // link to new one - this.font = ewol::resource::TexturedFont::create(_fontName); - if (this.font == null) { - Log.error("Can not get font resource"); - this.font = previousFont; - } -} - -void ewol::compositing::Text::setFontMode(enum ewol::font::mode _mode) { - if (this.font != null) { - this.mode = this.font.getWrappingMode(_mode); - } -} - -void ewol::compositing::Text::printChar( Character _charcode) { - // get a pointer on the glyph property : - ewol::GlyphProperty* myGlyph = getGlyphPointer(_charcode); - if (null == myGlyph) { - Log.error(" font does not really existed ..."); - return; - } - int fontSize = getSize(); - int fontHeigh = getHeight(); - - // get the kerning ofset : - float kerningOffset = 0; - if (this.kerning == true) { - kerningOffset = myGlyph.kerningGet(this.previousCharcode); - if (kerningOffset != 0) { - //Log.debug("Kerning between : '" + this.previousCharcode + "''" + myGlyph.this.UVal + "' value : " + kerningOffset); - } - } - // 0x01 == 0x20 == ' '; - if (_charcode != 0x01) { - /* Bitmap position - * xA xB - * yC *------* - * | | - * | | - * yD *------* - */ - float dxA = this.position.x() + myGlyph.this.bearing.x() + kerningOffset; - float dxB = dxA + myGlyph.this.sizeTexture.x(); - float dyC = this.position.y() + myGlyph.this.bearing.y() + fontHeigh - fontSize; - float dyD = dyC - myGlyph.this.sizeTexture.y(); - - float tuA = myGlyph.this.texturePosStart.x(); - float tuB = tuA + myGlyph.this.texturePosSize.x(); - float tvC = myGlyph.this.texturePosStart.y(); - float tvD = tvC + myGlyph.this.texturePosSize.y(); - - - // Clipping and drawing area - if( this.clippingEnable == true - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM ( dxB < this.clippingPosStart.x() - || dxA > this.clippingPosStop.x() - || dyC < this.clippingPosStart.y() - || dyD > this.clippingPosStop.y() ) ) { - // Nothing to diplay ... - } else { - if (this.clippingEnable == true) { - // generata positions... - float TexSizeX = tuB - tuA; - if (dxA < this.clippingPosStart.x()) { - // clip display - float drawSize = this.clippingPosStart.x() - dxA; - // update element start display - dxA = this.clippingPosStart.x(); - float addElement = TexSizeX * drawSize / (float)myGlyph.this.sizeTexture.x(); - // update texture start X Pos - tuA += addElement; - } - if (dxB > this.clippingPosStop.x()) { - // clip display - float drawSize = dxB - this.clippingPosStop.x(); - // update element start display - dxB = this.clippingPosStop.x(); - float addElement = TexSizeX * drawSize / (float)myGlyph.this.sizeTexture.x(); - // update texture start X Pos - tuB -= addElement; - } - float TexSizeY = tvC - tvD; - if (dyC > this.clippingPosStop.y()) { - // clip display - float drawSize = dyC - this.clippingPosStop.y(); - // update element start display - dyC = this.clippingPosStop.y(); - float addElement = TexSizeY * drawSize / (float)myGlyph.this.sizeTexture.y(); - // update texture start X Pos - tvC -= addElement; - } - if (dyD < this.clippingPosStart.y()) { - // clip display - float drawSize = this.clippingPosStart.y() - dyD; - // update element start display - dyD = this.clippingPosStart.y(); - float addElement = TexSizeY * drawSize / (float)myGlyph.this.sizeTexture.y(); - // update texture start X Pos - tvD += addElement; - } - } - if( dxB <= dxA - || dyD >= dyC) { - // nothing to do ... - } else { - /* Bitmap position - * 0------1 - * | | - * | | - * 3------2 - */ - if (this.needDisplay == true) { - Vector3f bitmapDrawPos[4]; - bitmapDrawPos[0].setValue((int)dxA, (int)dyC, 0); - bitmapDrawPos[1].setValue((int)dxB, (int)dyC, 0); - bitmapDrawPos[2].setValue((int)dxB, (int)dyD, 0); - bitmapDrawPos[3].setValue((int)dxA, (int)dyD, 0); - /* texture Position : - * 0------1 - * | | - * | | - * 3------2 - */ - Vector2f texturePos[4]; - texturePos[0].setValue(tuA+this.mode, tvC); - texturePos[1].setValue(tuB+this.mode, tvC); - texturePos[2].setValue(tuB+this.mode, tvD); - texturePos[3].setValue(tuA+this.mode, tvD); - - // NOTE : Android does not support the Quads elements ... - /* Step 1 : - * ******** - * ****** - * **** - * ** - * - */ - // set texture coordonates : - this.VBO.pushOnBuffer(this.vboIdCoordText, texturePos[0]); - this.VBO.pushOnBuffer(this.vboIdCoordText, texturePos[1]); - this.VBO.pushOnBuffer(this.vboIdCoordText, texturePos[2]); - // set display positions : - this.VBO.pushOnBuffer(this.vboIdCoord, bitmapDrawPos[0]); - this.VBO.pushOnBuffer(this.vboIdCoord, bitmapDrawPos[1]); - this.VBO.pushOnBuffer(this.vboIdCoord, bitmapDrawPos[2]); - // set the color - this.VBO.pushOnBuffer(this.vboIdColor, this.color); - this.VBO.pushOnBuffer(this.vboIdColor, this.color); - this.VBO.pushOnBuffer(this.vboIdColor, this.color); - /* Step 2 : - * - * ** - * **** - * ****** - * ******** - */ - // set texture coordonates : - this.VBO.pushOnBuffer(this.vboIdCoordText, texturePos[0]); - this.VBO.pushOnBuffer(this.vboIdCoordText, texturePos[2]); - this.VBO.pushOnBuffer(this.vboIdCoordText, texturePos[3]); - // set display positions : - this.VBO.pushOnBuffer(this.vboIdCoord, bitmapDrawPos[0]); - this.VBO.pushOnBuffer(this.vboIdCoord, bitmapDrawPos[2]); - this.VBO.pushOnBuffer(this.vboIdCoord, bitmapDrawPos[3]); - // set the color - this.VBO.pushOnBuffer(this.vboIdColor, this.color); - this.VBO.pushOnBuffer(this.vboIdColor, this.color); - this.VBO.pushOnBuffer(this.vboIdColor, this.color); - } - } - } - } - // move the position : - //Log.debug(" 5 pos=" + this.position + " advance=" + myGlyph.this.advance.x() + " kerningOffset=" + kerningOffset); - this.position.setX(this.position.x() + myGlyph.this.advance.x() + kerningOffset); - //Log.debug(" 6 print '" + charcode + "' : start=" + this.sizeDisplayStart + " stop=" + this.sizeDisplayStop + " pos=" + this.position); - // Register the previous character - this.previousCharcode = _charcode; - this.VBO.flush(); - return; -} - - -Vector3f ewol::compositing::Text::calculateSizeChar( Character _charcode) { - // get a pointer on the glyph property : - ewol::GlyphProperty * myGlyph = getGlyphPointer(_charcode); - int fontHeigh = getHeight(); - if (myGlyph == null) { - if (this.font == null) { - Log.warning("no Glyph... in no font"); - } else { - Log.warning("no Glyph... in font : " + this.font.getName()); - } - return Vector3f((float)(0.2), - (float)(fontHeigh), - (float)(0.0)); - } - // get the kerning ofset : - float kerningOffset = 0.0; - if (this.kerning == true) { - kerningOffset = myGlyph.kerningGet(this.previousCharcode); - } - - Vector3f outputSize((float)(myGlyph.this.advance.x() + kerningOffset), - (float)(fontHeigh), - (float)(0.0)); - // Register the previous character - this.previousCharcode = _charcode; - return outputSize; -} - diff --git a/src/org/atriasoft/ewol/compositing/Text.java b/src/org/atriasoft/ewol/compositing/Text.java index a56dd20..7d2c374 100644 --- a/src/org/atriasoft/ewol/compositing/Text.java +++ b/src/org/atriasoft/ewol/compositing/Text.java @@ -1,56 +1,414 @@ + /** @file * @author Edouard DUPIN * @copyright 2011, Edouard DUPIN, all right reserved * @license MPL v2.0 (see license file) */ -#pragma once +package org.atriasoft.ewol.compositing; -#include +import java.util.ArrayList; +import java.util.List; -#include -#include -#include -#include -#include -#include -#include +import org.atriasoft.etk.Color; +import org.atriasoft.etk.math.Matrix4f; +import org.atriasoft.etk.math.Vector2f; +import org.atriasoft.etk.math.Vector3f; +import org.atriasoft.ewol.Ewol; +import org.atriasoft.ewol.internal.Log; +import org.atriasoft.ewol.resource.ResourceTexturedFont; +import org.atriasoft.ewol.resource.font.FontMode; +import org.atriasoft.ewol.resource.font.GlyphProperty; +import org.atriasoft.gale.backend3d.OpenGL; -#include +class Text extends TextBase { + protected ResourceTexturedFont font; // !< Font resources -namespace ewol { - namespace compositing { - class Text : public ewol::compositing::TextBase { - protected: - ememory::Ptr this.font; //!< Font resources - public: - /** - * @brief generic ructor - * @param[in] _fontName Name of the font that might be loaded - * @param[in] _fontSize size of the font that might be loaded - */ - Text( String _fontName="", int _fontSize=-1); - /** - * @brief generic destructor - */ - ~Text(); - public: - void drawD(boolean _disableDepthTest); - void drawMT( Matrix4f _transformationMatrix, boolean _enableDepthTest); - protected: - float this.size; - public: - float getHeight(); - float getSize(); - ewol::GlyphProperty * getGlyphPointer(Character _charcode); - - public: - void setFontSize(int _fontSize); - void setFontName( String _fontName); - void setFont(String _fontName, int _fontSize); - void setFontMode(enum ewol::font::mode _mode); - void printChar( Character _charcode); - Vector3f calculateSizeChar( Character _charcode); - }; + List pointPositions = new ArrayList<>(); + List texturePositions = new ArrayList<>(); + List colors = new ArrayList<>(); + + protected float size; + + /** + * @brief generic ructor + * @param[in] _fontName Name of the font that might be loaded + * @param[in] _fontSize size of the font that might be loaded + */ + public Text() { + this(""); } -} + public Text(final String _fontName) { + this(_fontName, -1); + } + + public Text(final String _fontName, final int _fontSize) { + setFont(_fontName, _fontSize); + } + + @Override + public Vector3f calculateSizeChar(final Character _charcode) { + // get a pointer on the glyph property : + GlyphProperty myGlyph = getGlyphPointer(_charcode); + int fontHeigh = (int) getHeight(); + if (myGlyph == null) { + if (this.font == null) { + Log.warning("no Glyph... in no font"); + } else { + Log.warning("no Glyph... in font : " + this.font.getName()); + } + return new Vector3f((float) (0.2), (fontHeigh), (float) (0.0)); + } + // get the kerning ofset : + float kerningOffset = 0.0f; + if (this.kerning == true) { + kerningOffset = myGlyph.kerningGet(this.previousCharcode); + } + + Vector3f outputSize = new Vector3f(myGlyph.advance.x() + kerningOffset, (fontHeigh), 0.0f); + // Register the previous character + this.previousCharcode = _charcode; + return outputSize; + } + + @Override + public void clear() { + // call upper class + super.clear(); + this.texturePositions.clear(); + // set display positions : + this.pointPositions.clear(); + // set the color + this.colors.clear(); + } + + @Override + public void drawD(final boolean _disableDepthTest) { + // draw BG in any case: + // TODO this.vectorialDraw.draw(_disableDepthTest); + + // TODO : do it only one time (when needed ...) + // set texture coordonates : + this.VBO.setVboData(vboIdCoordText, this.texturePositions.toArray(Vector3f[]::new)); + // set display positions : + this.VBO.setVboData(vboIdCoord, this.pointPositions.toArray(Vector2f[]::new)); + // set the color + this.VBO.setVboData(vboIdColor, this.colors.toArray(Color[]::new)); + // TODO : do it only one time (when needed ...) --------- end ------- + + if (this.VBO.bufferSize(TextBase.vboIdCoord) <= 0 || this.font == null) { + // Log.warning("Nothink to draw..."); + return; + } + if (this.font == null) { + Log.warning("no font..."); + return; + } + if (this.GLprogram == null) { + Log.error("No shader ..."); + return; + } + // set Matrix : translation/positionMatrix + Matrix4f tmpMatrix = OpenGL.getMatrix().multiply(this.matrixApply); + this.GLprogram.use(); + this.GLprogram.uniformMatrix(this.GLMatrix, tmpMatrix); + // Texture : + this.GLprogram.setTexture0(this.GLtexID, this.font.getRendererId()); + this.GLprogram.uniformInt(this.GLtextWidth, this.font.getOpenGlSize().x()); + this.GLprogram.uniformInt(this.GLtextHeight, this.font.getOpenGlSize().x()); + // position: + this.GLprogram.sendAttributePointer(this.GLPosition, this.VBO, TextBase.vboIdCoord); + // Texture: + this.GLprogram.sendAttributePointer(this.GLtexture, this.VBO, TextBase.vboIdCoordText); + // color: + this.GLprogram.sendAttributePointer(this.GLColor, this.VBO, TextBase.vboIdColor); + // Request the draw od the elements : + OpenGL.drawArrays(OpenGL.RenderMode.triangle, 0, this.VBO.bufferSize(TextBase.vboIdCoord)); + this.GLprogram.unUse(); + } + + @Override + public void drawMT(final Matrix4f _transformationMatrix, final boolean _enableDepthTest) { + + // draw BG in any case: + // TODO this.vectorialDraw.draw(); + + // TODO : do it only one time (when needed ...) + // set texture coordonates : + this.VBO.setVboData(vboIdCoordText, this.texturePositions.toArray(Vector3f[]::new)); + // set display positions : + this.VBO.setVboData(vboIdCoord, this.pointPositions.toArray(Vector2f[]::new)); + // set the color + this.VBO.setVboData(vboIdColor, this.colors.toArray(Color[]::new)); + // TODO : do it only one time (when needed ...) --------- end ------- + + if (this.VBO.bufferSize(TextBase.vboIdCoord) <= 0 || this.font == null) { + // TODO : set it back ... + // Log.warning("Nothink to draw..."); + return; + } + if (this.font == null) { + Log.warning("no font..."); + return; + } + if (this.GLprogram == null) { + Log.error("No shader ..."); + return; + } + if (_enableDepthTest == true) { + OpenGL.enable(OpenGL.Flag.flag_depthTest); + } + // set Matrix : translation/positionMatrix + Matrix4f projMatrix = OpenGL.getMatrix(); + Matrix4f camMatrix = OpenGL.getCameraMatrix(); + Matrix4f tmpMatrix = projMatrix.multiply(camMatrix).multiply(_transformationMatrix); + this.GLprogram.use(); + this.GLprogram.uniformMatrix(this.GLMatrix, tmpMatrix); + // Texture: + this.GLprogram.setTexture0(this.GLtexID, this.font.getRendererId()); + this.GLprogram.uniformInt(this.GLtextWidth, this.font.getOpenGlSize().x()); + this.GLprogram.uniformInt(this.GLtextHeight, this.font.getOpenGlSize().x()); + // position: + this.GLprogram.sendAttributePointer(this.GLPosition, this.VBO, TextBase.vboIdCoord); + // Texture: + this.GLprogram.sendAttributePointer(this.GLtexture, this.VBO, TextBase.vboIdCoordText); + // color: + this.GLprogram.sendAttributePointer(this.GLColor, this.VBO, TextBase.vboIdColor); + // Request the draw od the elements: + OpenGL.drawArrays(OpenGL.RenderMode.triangle, 0, this.VBO.bufferSize(TextBase.vboIdCoord)); + this.GLprogram.unUse(); + if (_enableDepthTest == true) { + OpenGL.disable(OpenGL.Flag.flag_depthTest); + } + } + + @Override + public GlyphProperty getGlyphPointer(final Character _charcode) { + if (this.font == null) { + Log.warning("no font..."); + return null; + } + return this.font.getGlyph(_charcode, this.mode); + } + + @Override + public float getHeight() { + if (this.font == null) { + Log.warning("no font..."); + return 10.0f; + } + return this.font.getHeight(this.mode); + } + + @Override + public float getSize() { + if (this.font == null) { + Log.warning("no font..."); + return 1.0f; + } + return this.font.getFontSize(); + } + + @Override + public void printChar(final Character _charcode) { + // get a pointer on the glyph property : + GlyphProperty myGlyph = getGlyphPointer(_charcode); + if (myGlyph == null) { + Log.error(" font does not really existed ..."); + return; + } + int fontSize = (int) getSize(); + int fontHeigh = (int) getHeight(); + + // get the kerning ofset : + float kerningOffset = 0; + if (this.kerning == true) { + kerningOffset = myGlyph.kerningGet(this.previousCharcode); + if (kerningOffset != 0) { + // Log.debug("Kerning between : '" + this.previousCharcode + "''" + myGlyph.UVal + // + "' value : " + kerningOffset); + } + } + // 0x01 == 0x20 == ' '; + if (_charcode != 0x01) { + /* + * Bitmap position xA xB yC *------* | | | | yD *------* + */ + float dxA = this.position.x() + myGlyph.bearing.x() + kerningOffset; + float dxB = dxA + myGlyph.sizeTexture.x(); + float dyC = this.position.y() + myGlyph.bearing.y() + fontHeigh - fontSize; + float dyD = dyC - myGlyph.sizeTexture.y(); + + float tuA = myGlyph.texturePosStart.x(); + float tuB = tuA + myGlyph.texturePosSize.x(); + float tvC = myGlyph.texturePosStart.y(); + float tvD = tvC + myGlyph.texturePosSize.y(); + + // Clipping and drawing area + if (this.clippingEnable == true && (dxB < this.clippingPosStart.x() || dxA > this.clippingPosStop.x() + || dyC < this.clippingPosStart.y() || dyD > this.clippingPosStop.y())) { + // Nothing to diplay ... + } else { + if (this.clippingEnable == true) { + // generata positions... + float TexSizeX = tuB - tuA; + if (dxA < this.clippingPosStart.x()) { + // clip display + float drawSize = this.clippingPosStart.x() - dxA; + // update element start display + dxA = this.clippingPosStart.x(); + float addElement = TexSizeX * drawSize / myGlyph.sizeTexture.x(); + // update texture start X Pos + tuA += addElement; + } + if (dxB > this.clippingPosStop.x()) { + // clip display + float drawSize = dxB - this.clippingPosStop.x(); + // update element start display + dxB = this.clippingPosStop.x(); + float addElement = TexSizeX * drawSize / myGlyph.sizeTexture.x(); + // update texture start X Pos + tuB -= addElement; + } + float TexSizeY = tvC - tvD; + if (dyC > this.clippingPosStop.y()) { + // clip display + float drawSize = dyC - this.clippingPosStop.y(); + // update element start display + dyC = this.clippingPosStop.y(); + float addElement = TexSizeY * drawSize / myGlyph.sizeTexture.y(); + // update texture start X Pos + tvC -= addElement; + } + if (dyD < this.clippingPosStart.y()) { + // clip display + float drawSize = this.clippingPosStart.y() - dyD; + // update element start display + dyD = this.clippingPosStart.y(); + float addElement = TexSizeY * drawSize / myGlyph.sizeTexture.y(); + // update texture start X Pos + tvD += addElement; + } + } + if (dxB <= dxA || dyD >= dyC) { + // nothing to do ... + } else { + /* + * Bitmap position 0------1 | | | | 3------2 + */ + if (this.needDisplay == true) { + Vector3f drawPosition0 = new Vector3f((int) dxA, (int) dyC, 0); + Vector3f drawPosition1 = new Vector3f((int) dxB, (int) dyC, 0); + Vector3f drawPosition2 = new Vector3f((int) dxB, (int) dyD, 0); + Vector3f drawPosition3 = new Vector3f((int) dxA, (int) dyD, 0); + /* + * texture Position : 0------1 | | | | 3------2 + */ + Vector2f texturePos0 = new Vector2f(tuA + this.mode.getValue(), tvC); + Vector2f texturePos1 = new Vector2f(tuB + this.mode.getValue(), tvC); + Vector2f texturePos2 = new Vector2f(tuB + this.mode.getValue(), tvD); + Vector2f texturePos3 = new Vector2f(tuA + this.mode.getValue(), tvD); + + // NOTE : Android does not support the Quads elements ... + /* + * Step 1 : ******** ****** **** ** + * + */ + // set texture coordonates : + this.texturePositions.add(texturePos0); + this.texturePositions.add(texturePos1); + this.texturePositions.add(texturePos2); + // set display positions : + this.pointPositions.add(drawPosition0); + this.pointPositions.add(drawPosition1); + this.pointPositions.add(drawPosition2); + // set the color + this.colors.add(this.color); + this.colors.add(this.color); + this.colors.add(this.color); + /* + * Step 2 : + * + * ** **** ****** ******** + */ + // set texture coordonates : + this.texturePositions.add(texturePos0); + this.texturePositions.add(texturePos2); + this.texturePositions.add(texturePos3); + // set display positions : + this.pointPositions.add(drawPosition0); + this.pointPositions.add(drawPosition2); + this.pointPositions.add(drawPosition3); + // set the color + this.colors.add(this.color); + this.colors.add(this.color); + this.colors.add(this.color); + } + } + } + } + // move the position : + // Log.debug(" 5 pos=" + this.position + " advance=" + myGlyph.advance.x() + " + // kerningOffset=" + kerningOffset); + this.position = this.position.withX(this.position.x() + myGlyph.advance.x() + kerningOffset); + // Log.debug(" 6 print '" + charcode + "' : start=" + this.sizeDisplayStart + " + // stop=" + this.sizeDisplayStop + " pos=" + this.position); + // Register the previous character + this.previousCharcode = _charcode; + this.VBO.flush(); + return; + } + + @Override + public void setFont(String _fontName, int _fontSize) { + clear(); + // remove old one + ResourceTexturedFont previousFont = this.font; + if (_fontSize <= 0) { + _fontSize = Ewol.getContext().getFontDefault().getSize(); + } + if (_fontName == "") { + _fontName = Ewol.getContext().getFontDefault().getName(); + } + _fontName += ":"; + _fontName += _fontSize; + Log.verbose("plop : " + _fontName + " size=" + _fontSize + " result :" + _fontName); + // link to new one + this.font = ResourceTexturedFont.create(_fontName); + if (this.font == null) { + Log.error("Can not get font resource"); + this.font = previousFont; + } + } + + @Override + public void setFontMode(final FontMode _mode) { + if (this.font != null) { + this.mode = this.font.getWrappingMode(_mode); + } + } + + @Override + public void setFontName(final String _fontName) { + // get old size + int fontSize = -1; + if (this.font != null) { + fontSize = this.font.getFontSize(); + } + setFont(_fontName, fontSize); + } + + @Override + public void setFontSize(final int _fontSize) { + // get old size + String fontName = ""; + if (this.font != null) { + fontName = this.font.getName(); + // Remove the :XX for the size ... + int pos = fontName.lastIndexOf(':'); + fontName = fontName.substring(0, pos); + } + setFont(fontName, _fontSize); + } + +}; diff --git a/src/org/atriasoft/ewol/compositing/TextBase.cpp b/src/org/atriasoft/ewol/compositing/TextBase.cpp deleted file mode 100644 index b0ef78e..0000000 --- a/src/org/atriasoft/ewol/compositing/TextBase.cpp +++ /dev/null @@ -1,1116 +0,0 @@ -/** @file - * @author Edouard DUPIN - * @copyright 2011, Edouard DUPIN, all right reserved - * @license MPL v2.0 (see license file) - */ - -#include -#include -#include -#include - -#include -ETK_DECLARE_TYPE(ewol::compositing::TextBase); - - int ewol::compositing::TextBase::this.vboIdCoord(0); - int ewol::compositing::TextBase::this.vboIdCoordText(1); - int ewol::compositing::TextBase::this.vboIdColor(2); - int ewol::compositing::TextBase::this.vboIdGlyphLevel(3); -#define NB_VBO (4) - -ewol::compositing::TextBase::TextBase( String _shaderName, boolean _loadProgram) : - this.position(0.0, 0.0, 0.0), - this.clippingPosStart(0.0, 0.0, 0.0), - this.clippingPosStop(0.0, 0.0, 0.0), - this.clippingEnable(false), - this.defaultColorFg(etk::color::black), - this.defaultColorBg(etk::color::none), - this.color(etk::color::black), - this.colorBg(etk::color::none), - this.colorCursor(etk::color::black), - this.colorSelection(etk::color::olive), - this.mode(ewol::font::Regular), - this.kerning(true), - this.previousCharcode(0), - this.startTextpos(0), - this.stopTextPos(0), - this.alignement(alignDisable), - this.GLprogram(null), - this.GLPosition(-1), - this.GLMatrix(-1), - this.GLColor(-1), - this.GLtexture(-1), - this.GLtexID(-1), - this.selectionStartPos(-100), - this.cursorPos(-100) { - if (_loadProgram == true) { - loadProgram(_shaderName); - } - // Create the VBO: - this.VBO = gale::resource::VirtualBufferObject::create(NB_VBO); - if (this.VBO == null) { - Log.error("can not instanciate VBO ..."); - return; - } - // TO facilitate some debugs we add a name of the VBO: - this.VBO.setName("[VBO] of ewol::compositing::TextBase"); -} - - -ewol::compositing::TextBase::~TextBase() { - -} - -void ewol::compositing::TextBase::loadProgram( String _shaderName) { - // get the shader resource: - this.GLPosition = 0; - ememory::Ptr old = this.GLprogram; - this.GLprogram = gale::resource::Program::create(_shaderName); - if (this.GLprogram != null) { - this.GLPosition = this.GLprogram.getAttribute("EW_coord3d"); - this.GLColor = this.GLprogram.getAttribute("EW_color"); - this.GLtexture = this.GLprogram.getAttribute("EW_texture2d"); - this.GLMatrix = this.GLprogram.getUniform("EW_MatrixTransformation"); - this.GLtexID = this.GLprogram.getUniform("EW_texID"); - this.GLtextWidth = this.GLprogram.getUniform("EW_texWidth"); - this.GLtextHeight = this.GLprogram.getUniform("EW_texHeight"); - } else { - Log.error("Can not load the program => create previous one..."); - this.GLprogram = old; - old = null; - } -} - -void ewol::compositing::TextBase::translate( Vector3f _vect) { - ewol::Compositing::translate(_vect); - this.vectorialDraw.translate(_vect); -} - -void ewol::compositing::TextBase::rotate( Vector3f _vect, float _angle) { - ewol::Compositing::rotate(_vect, _angle); - this.vectorialDraw.rotate(_vect, _angle); -} - -void ewol::compositing::TextBase::scale( Vector3f _vect) { - ewol::Compositing::scale(_vect); - this.vectorialDraw.scale(_vect); -} - -void ewol::compositing::TextBase::clear() { - // call upper class - ewol::Compositing::clear(); - // remove sub draw system - this.vectorialDraw.clear(); - // reset Buffer: - this.VBO.clear(); - // reset temporal variables: - reset(); -} - -void ewol::compositing::TextBase::reset() { - this.position = Vector3f(0,0,0); - this.clippingPosStart = Vector3f(0,0,0); - this.clippingPosStop = Vector3f(0,0,0); - this.sizeDisplayStart = this.position; - this.sizeDisplayStop = this.position; - this.nbCharDisplayed = 0; - this.clippingEnable = false; - this.color = this.defaultColorFg; - this.colorBg = this.defaultColorBg; - this.mode = ewol::font::Regular; - this.previousCharcode = 0; - this.startTextpos = 0; - this.stopTextPos = 0; - this.alignement = alignDisable; - this.htmlCurrrentLine = U""; - this.selectionStartPos = -100; - this.cursorPos = -100; - this.htmlDecoration.clear(); - this.needDisplay = true; - this.nbCharDisplayed = 0; -} - -void ewol::compositing::TextBase::setPos( Vector3f _pos) { - // check min max for display area - if (this.nbCharDisplayed != 0) { - Log.verbose("update size 1 " + this.sizeDisplayStart + " " + this.sizeDisplayStop); - this.sizeDisplayStop.setX(etk::max(this.position.x(), this.sizeDisplayStop.x())); - this.sizeDisplayStop.setY(etk::max(this.position.y(), this.sizeDisplayStop.y())); - this.sizeDisplayStart.setX(etk::min(this.position.x(), this.sizeDisplayStart.x())); - this.sizeDisplayStart.setY(etk::min(this.position.y(), this.sizeDisplayStart.y())); - Log.verbose("update size 2 " + this.sizeDisplayStart + " " + this.sizeDisplayStop); - } - // update position - this.position = _pos; - this.previousCharcode = 0; - this.vectorialDraw.setPos(this.position); - // update min max of the display area: - if (this.nbCharDisplayed == 0) { - this.sizeDisplayStart = this.position; - this.sizeDisplayStop = this.position; - this.sizeDisplayStop.setY( this.sizeDisplayStop.y()+ getHeight()); - Log.verbose("update size 0 " + this.sizeDisplayStart + " " + this.sizeDisplayStop); - } else { - Log.verbose("update size 3 " + this.sizeDisplayStart + " " + this.sizeDisplayStop); - this.sizeDisplayStop.setX(etk::max(this.position.x(), this.sizeDisplayStop.x())); - this.sizeDisplayStop.setY(etk::max(this.position.y(), this.sizeDisplayStop.y())); - this.sizeDisplayStart.setX(etk::min(this.position.x(), this.sizeDisplayStart.x())); - this.sizeDisplayStart.setY(etk::min(this.position.y(), this.sizeDisplayStart.y())); - Log.verbose("update size 4 " + this.sizeDisplayStart + " " + this.sizeDisplayStop); - } -} - -void ewol::compositing::TextBase::setRelPos( Vector3f _pos) { - this.position += _pos; - this.previousCharcode = 0; - this.vectorialDraw.setPos(this.position); -} - -void ewol::compositing::TextBase::setColorBg( etk::Color<> _color) { - this.colorBg = _color; - this.vectorialDraw.setColor(_color); -} - -void ewol::compositing::TextBase::setClipping( Vector3f _pos, Vector3f _posEnd) { - // note the internal system all time request to have a bounding all time in the same order - if (_pos.x() <= _posEnd.x()) { - this.clippingPosStart.setX(_pos.x()); - this.clippingPosStop.setX(_posEnd.x()); - } else { - this.clippingPosStart.setX(_posEnd.x()); - this.clippingPosStop.setX(_pos.x()); - } - if (_pos.y() <= _posEnd.y()) { - this.clippingPosStart.setY(_pos.y()); - this.clippingPosStop.setY(_posEnd.y()); - } else { - this.clippingPosStart.setY(_posEnd.y()); - this.clippingPosStop.setY(_pos.y()); - } - if (_pos.z() <= _posEnd.z()) { - this.clippingPosStart.setZ(_pos.z()); - this.clippingPosStop.setZ(_posEnd.z()); - } else { - this.clippingPosStart.setZ(_posEnd.z()); - this.clippingPosStop.setZ(_pos.z()); - } - this.clippingEnable = true; - //this.vectorialDraw.setClipping(this.clippingPosStart, this.clippingPosStop); -} - -void ewol::compositing::TextBase::setClippingMode(boolean _newMode) { - this.clippingEnable = _newMode; - //this.vectorialDraw.setClippingMode(this.clippingEnable); -} - -void ewol::compositing::TextBase::setFontBold(boolean _status) { - if (_status == true) { - // enable - if (this.mode == ewol::font::Regular) { - setFontMode(ewol::font::Bold); - } else if (this.mode == ewol::font::Italic) { - setFontMode(ewol::font::BoldItalic); - } - } else { - // disable - if (this.mode == ewol::font::Bold) { - setFontMode(ewol::font::Regular); - } else if (this.mode == ewol::font::BoldItalic) { - setFontMode(ewol::font::Italic); - } - } -} - -void ewol::compositing::TextBase::setFontItalic(boolean _status) { - if (_status == true) { - // enable - if (this.mode == ewol::font::Regular) { - setFontMode(ewol::font::Italic); - } else if (this.mode == ewol::font::Bold) { - setFontMode(ewol::font::BoldItalic); - } - } else { - // disable - if (this.mode == ewol::font::Italic) { - setFontMode(ewol::font::Regular); - } else if (this.mode == ewol::font::BoldItalic) { - setFontMode(ewol::font::Bold); - } - } -} - -void ewol::compositing::TextBase::setKerningMode(boolean _newMode) { - this.kerning = _newMode; -} - -void ewol::compositing::TextBase::print( etk::UString _text) { - List decorationEmpty; - print(_text, decorationEmpty); -} - -void ewol::compositing::TextBase::print( String _text) { - List decorationEmpty; - print(_text, decorationEmpty); -} - - -void ewol::compositing::TextBase::parseHtmlNode( exml::Element _element) { - // get the static real pointer - if (_element.exist() == false) { - Log.error( "Error Input node does not existed ..."); - return; - } - for(auto it : _element.nodes) { - if (it.isComment() == true) { - // nothing to do ... - continue; - } else if (it.isText() == true) { - htmlAddData(etk::toUString(it.getValue())); - Log.verbose("XML add : " + it.getValue()); - continue; - } else if (it.isElement() == false) { - Log.error("(l "+ it.getPos() + ") node not suported type : " + it.getType() + " val='"+ it.getValue() + "'" ); - continue; - } - exml::Element elem = it.toElement(); - if (elem.exist() == false) { - Log.error("Cast error ..."); - continue; - } - if(etk::compare_no_case(elem.getValue(), "br") == true) { - htmlFlush(); - Log.verbose("XML flush newLine"); - forceLineReturn(); - } else if (etk::compare_no_case(elem.getValue(), "font") == true) { - Log.verbose("XML Font ..."); - TextDecoration tmpDeco = this.htmlDecoTmp; - String colorValue = elem.attributes["color"]; - if (colorValue.size() != 0) { - this.htmlDecoTmp.this.colorFg = colorValue; - } - colorValue = elem.attributes["colorBg"]; - if (colorValue.size() != 0) { - this.htmlDecoTmp.this.colorBg = colorValue; - } - parseHtmlNode(elem); - this.htmlDecoTmp = tmpDeco; - } else if( etk::compare_no_case(elem.getValue(), "b") == true - || etk::compare_no_case(elem.getValue(), "bold") == true) { - Log.verbose("XML bold ..."); - TextDecoration tmpDeco = this.htmlDecoTmp; - if (this.htmlDecoTmp.this.mode == ewol::font::Regular) { - this.htmlDecoTmp.this.mode = ewol::font::Bold; - } else if (this.htmlDecoTmp.this.mode == ewol::font::Italic) { - this.htmlDecoTmp.this.mode = ewol::font::BoldItalic; - } - parseHtmlNode(elem); - this.htmlDecoTmp = tmpDeco; - } else if( etk::compare_no_case(elem.getValue(), "i") == true - || etk::compare_no_case(elem.getValue(), "italic") == true) { - Log.verbose("XML italic ..."); - TextDecoration tmpDeco = this.htmlDecoTmp; - if (this.htmlDecoTmp.this.mode == ewol::font::Regular) { - this.htmlDecoTmp.this.mode = ewol::font::Italic; - } else if (this.htmlDecoTmp.this.mode == ewol::font::Bold) { - this.htmlDecoTmp.this.mode = ewol::font::BoldItalic; - } - parseHtmlNode(elem); - this.htmlDecoTmp = tmpDeco; - } else if( etk::compare_no_case(elem.getValue(), "u") == true - || etk::compare_no_case(elem.getValue(), "underline") == true) { - Log.verbose("XML underline ..."); - parseHtmlNode(elem); - } else if( etk::compare_no_case(elem.getValue(), "p") == true - || etk::compare_no_case(elem.getValue(), "paragraph") == true) { - Log.verbose("XML paragraph ..."); - htmlFlush(); - this.alignement = alignLeft; - forceLineReturn(); - parseHtmlNode(elem); - forceLineReturn(); - } else if (etk::compare_no_case(elem.getValue(), "center") == true) { - Log.verbose("XML center ..."); - htmlFlush(); - this.alignement = alignCenter; - parseHtmlNode(elem); - } else if (etk::compare_no_case(elem.getValue(), "left") == true) { - Log.verbose("XML left ..."); - htmlFlush(); - this.alignement = alignLeft; - parseHtmlNode(elem); - } else if (etk::compare_no_case(elem.getValue(), "right") == true) { - Log.verbose("XML right ..."); - htmlFlush(); - this.alignement = alignRight; - parseHtmlNode(elem); - } else if (etk::compare_no_case(elem.getValue(), "justify") == true) { - Log.verbose("XML justify ..."); - htmlFlush(); - this.alignement = alignJustify; - parseHtmlNode(elem); - } else { - Log.error("(l "+ elem.getPos() + ") node not suported type: " + elem.getType() + " val='"+ elem.getValue() + "'" ); - } - } -} - -void ewol::compositing::TextBase::printDecorated( String _text) { - String tmpData("\n\n"); - tmpData += _text; - tmpData += "\n\n\n"; - //Log.debug("plop : " + tmpData); - printHTML(tmpData); -} - -void ewol::compositing::TextBase::printDecorated( etk::UString _text) { - etk::UString tmpData(U"\n\n"); - tmpData += _text; - tmpData += U"\n\n\n"; - //Log.debug("plop : " + tmpData); - printHTML(tmpData); -} - -void ewol::compositing::TextBase::printHTML( String _text) { - exml::Document doc; - - // reset parameter : - this.htmlDecoTmp.this.colorBg = this.defaultColorBg; - this.htmlDecoTmp.this.colorFg = this.defaultColorFg; - this.htmlDecoTmp.this.mode = ewol::font::Regular; - - if (doc.parse(_text) == false) { - Log.error( "can not load XML: PARSING error: Decorated text "); - return; - } - - exml::Element root = doc.nodes["html"]; - if (root.exist() == false) { - Log.error( "can not load XML: main node not find: 'html'"); - doc.display(); - return; - } - exml::Element bodyNode = root.nodes["body"]; - if (root.exist() == false) { - Log.error( "can not load XML: main node not find: 'body'"); - return; - } - parseHtmlNode(bodyNode); - htmlFlush(); -} - -void ewol::compositing::TextBase::printHTML( etk::UString _text) { - exml::Document doc; - - // reset parameter : - this.htmlDecoTmp.this.colorBg = this.defaultColorBg; - this.htmlDecoTmp.this.colorFg = this.defaultColorFg; - this.htmlDecoTmp.this.mode = ewol::font::Regular; - // TODO : Create an instance of xml parser to manage etk::UString... - if (doc.parse(etk::toString(_text)) == false) { - Log.error( "can not load XML: PARSING error: Decorated text "); - return; - } - - exml::Element root = doc.nodes["html"]; - if (root.exist() == false) { - Log.error( "can not load XML: main node not find: 'html'"); - doc.display(); - return; - } - exml::Element bodyNode = root.nodes["body"]; - if (root.exist() == false) { - Log.error( "can not load XML: main node not find: 'body'"); - return; - } - parseHtmlNode(bodyNode); - htmlFlush(); -} - -void ewol::compositing::TextBase::print( String _text, List _decoration) { - etk::Color<> tmpFg(this.color); - etk::Color<> tmpBg(this.colorBg); - if (this.alignement == alignDisable) { - //Log.debug(" 1 print in not alligned mode : start=" + this.sizeDisplayStart + " stop=" + this.sizeDisplayStop + " pos=" + this.position); - // display the cursor if needed (if it is at the start position...) - if (this.needDisplay == true) { - if (0 == this.cursorPos) { - this.vectorialDraw.setPos(this.position); - setColorBg(this.colorCursor); - printCursor(false); - } - } - // note this is faster when nothing is requested ... - for(int iii=0; iii<_text.size(); iii++) { - // check if ve have decoration - if (iii<_decoration.size()) { - tmpFg = _decoration[iii].this.colorFg; - tmpBg = _decoration[iii].this.colorBg; - setFontMode(_decoration[iii].this.mode); - } - // if real display : ( not display is for size calculation) - if (this.needDisplay == true) { - if( ( this.selectionStartPos-1 < (long)iii - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM (long)iii <= this.cursorPos-1) - || ( this.selectionStartPos-1 >= (long)iii - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM (long)iii > this.cursorPos-1) ) { - setColor( 0x000000FF); - setColorBg(this.colorSelection); - } else { - setColor( tmpFg); - setColorBg(tmpBg); - } - } - if( this.needDisplay == true - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM this.colorBg.a() != 0) { - Vector3f pos = this.position; - this.vectorialDraw.setPos(pos); - printChar(_text[iii]); - float fontHeigh = getHeight(); - this.vectorialDraw.rectangleWidth(Vector3f(this.position.x()-pos.x(),fontHeigh,0.0f) ); - this.nbCharDisplayed++; - } else { - printChar(_text[iii]); - this.nbCharDisplayed++; - } - // display the cursor if needed (if it is at the other position...) - if (this.needDisplay == true) { - if ((long)iii == this.cursorPos-1) { - this.vectorialDraw.setPos(this.position); - setColorBg(this.colorCursor); - printCursor(false); - } - } - } - //Log.debug(" 2 print in not alligned mode : start=" + this.sizeDisplayStart + " stop=" + this.sizeDisplayStop + " pos=" + this.position); - } else { - //Log.debug(" 3 print in not alligned mode : start=" + this.sizeDisplayStart + " stop=" + this.sizeDisplayStop + " pos=" + this.position); - // special start case at the right of the endpoint : - if (this.stopTextPos < this.position.x()) { - forceLineReturn(); - } - float basicSpaceWidth = calculateSize(Character(' ')).x(); - int currentId = 0; - int stop; - int space; - int freeSpace; - while (currentId < (long)_text.size()) { - boolean needNoJustify = extrapolateLastId(_text, currentId, stop, space, freeSpace); - float interpolation = basicSpaceWidth; - switch (this.alignement) { - case alignJustify: - if (needNoJustify == false) { - interpolation += (float)freeSpace / (float)(space-1); - } - break; - case alignDisable: // must not came from here ... - case alignLeft: - // nothing to do ... - break; - case alignRight: - if (this.needDisplay == true) { - // Move the first char at the right : - setPos(Vector3f(this.position.x() + freeSpace, - this.position.y(), - this.position.z()) ); - } - break; - case alignCenter: - if (this.needDisplay == true) { - // Move the first char at the right : - setPos(Vector3f(this.position.x() + freeSpace/2, - this.position.y(), - this.position.z()) ); - } - break; - } - // display all the elements - if( this.needDisplay == true - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM this.cursorPos == 0) { - this.vectorialDraw.setPos(this.position); - setColorBg(this.colorCursor); - printCursor(false); - } - for(int iii=currentId; (long)iii= (long)iii - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM (long)iii > this.cursorPos-1) ) { - setColor( 0x000000FF); - setColorBg(this.colorSelection); - } else { - setColor( tmpFg); - setColorBg(tmpBg); - } - } - // special for the justify mode - if ((Character)_text[iii] == u32char::Space) { - //Log.debug(" generateString : \" \""); - if( this.needDisplay == true - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM this.colorBg.a() != 0) { - this.vectorialDraw.setPos(this.position); - } - // Must generate a dynamic space : - setPos(Vector3f(this.position.x() + interpolation, - this.position.y(), - this.position.z()) ); - if( this.needDisplay == true - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM this.colorBg.a() != 0) { - this.vectorialDraw.rectangleWidth(Vector3f(interpolation,fontHeigh,0.0f) ); - } - } else { - //Log.debug(" generateString : \"" + (char)text[iii] + "\""); - if( this.needDisplay == true - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM this.colorBg.a() != 0) { - Vector3f pos = this.position; - this.vectorialDraw.setPos(pos); - printChar(_text[iii]); - this.vectorialDraw.rectangleWidth(Vector3f(this.position.x()-pos.x(),fontHeigh,0.0f) ); - this.nbCharDisplayed++; - } else { - printChar(_text[iii]); - this.nbCharDisplayed++; - } - } - if (this.needDisplay == true) { - if ((long)iii == this.cursorPos-1) { - this.vectorialDraw.setPos(this.position); - setColorBg(this.colorCursor); - printCursor(false); - } - } - } - if (currentId == stop) { - currentId++; - } else if((Character)_text[stop] == u32char::Space) { - currentId = stop+1; - // reset position : - setPos(Vector3f(this.startTextpos, - (float)(this.position.y() - getHeight()), - this.position.z()) ); - this.nbCharDisplayed++; - } else if((Character)_text[stop] == u32char::Return) { - currentId = stop+1; - // reset position : - setPos(Vector3f(this.startTextpos, - (float)(this.position.y() - getHeight()), - this.position.z()) ); - this.nbCharDisplayed++; - } else { - currentId = stop; - } - } - //Log.debug(" 4 print in not alligned mode : start=" + this.sizeDisplayStart + " stop=" + this.sizeDisplayStop + " pos=" + this.position); - } -} - -void ewol::compositing::TextBase::print( etk::UString _text, List _decoration) { - etk::Color<> tmpFg(this.color); - etk::Color<> tmpBg(this.colorBg); - if (this.alignement == alignDisable) { - //Log.debug(" 1 print in not alligned mode : start=" + this.sizeDisplayStart + " stop=" + this.sizeDisplayStop + " pos=" + this.position); - // display the cursor if needed (if it is at the start position...) - if (this.needDisplay == true) { - if (0 == this.cursorPos) { - this.vectorialDraw.setPos(this.position); - setColorBg(this.colorCursor); - printCursor(false); - } - } - // note this is faster when nothing is requested ... - for(int iii=0; iii<_text.size(); iii++) { - // check if ve have decoration - if (iii<_decoration.size()) { - tmpFg = _decoration[iii].this.colorFg; - tmpBg = _decoration[iii].this.colorBg; - setFontMode(_decoration[iii].this.mode); - } - // if real display : ( not display is for size calculation) - if (this.needDisplay == true) { - if( ( this.selectionStartPos-1<(long)iii - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM (long)iii <= this.cursorPos-1) - || ( this.selectionStartPos-1 >= (long)iii - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM (long)iii > this.cursorPos-1) ) { - setColor( 0x000000FF); - setColorBg(this.colorSelection); - } else { - setColor( tmpFg); - setColorBg(tmpBg); - } - } - if( this.needDisplay == true - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM this.colorBg.a() != 0) { - Vector3f pos = this.position; - this.vectorialDraw.setPos(pos); - printChar(_text[iii]); - float fontHeigh = getHeight(); - this.vectorialDraw.rectangleWidth(Vector3f(this.position.x()-pos.x(),fontHeigh,0.0f) ); - this.nbCharDisplayed++; - } else { - printChar(_text[iii]); - this.nbCharDisplayed++; - } - // display the cursor if needed (if it is at the other position...) - if (this.needDisplay == true) { - if ((long)iii == this.cursorPos-1) { - this.vectorialDraw.setPos(this.position); - setColorBg(this.colorCursor); - printCursor(false); - } - } - } - //Log.debug(" 2 print in not alligned mode : start=" + this.sizeDisplayStart + " stop=" + this.sizeDisplayStop + " pos=" + this.position); - } else { - //Log.debug(" 3 print in not alligned mode : start=" + this.sizeDisplayStart + " stop=" + this.sizeDisplayStop + " pos=" + this.position); - // special start case at the right of the endpoint : - if (this.stopTextPos < this.position.x()) { - forceLineReturn(); - } - float basicSpaceWidth = calculateSize(Character(' ')).x(); - int currentId = 0; - int stop; - int space; - int freeSpace; - while (currentId < (long)_text.size()) { - boolean needNoJustify = extrapolateLastId(_text, currentId, stop, space, freeSpace); - float interpolation = basicSpaceWidth; - switch (this.alignement) { - case alignJustify: - if (needNoJustify == false) { - interpolation += (float)freeSpace / (float)(space-1); - } - break; - case alignDisable: // must not came from here ... - case alignLeft: - // nothing to do ... - break; - case alignRight: - if (this.needDisplay == true) { - // Move the first char at the right : - setPos(Vector3f(this.position.x() + freeSpace, - this.position.y(), - this.position.z()) ); - } - break; - case alignCenter: - if (this.needDisplay == true) { - // Move the first char at the right : - setPos(Vector3f(this.position.x() + freeSpace/2, - this.position.y(), - this.position.z()) ); - } - break; - } - // display all the elements - if( this.needDisplay == true - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM this.cursorPos == 0) { - this.vectorialDraw.setPos(this.position); - setColorBg(this.colorCursor); - printCursor(false); - } - for(int iii=currentId; (long)iii= (long)iii - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM (long)iii > this.cursorPos-1) ) { - setColor( 0x000000FF); - setColorBg(this.colorSelection); - } else { - setColor( tmpFg); - setColorBg(tmpBg); - } - } - // special for the justify mode - if ((Character)_text[iii] == u32char::Space) { - //Log.debug(" generateString : \" \""); - if( this.needDisplay == true - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM this.colorBg.a() != 0) { - this.vectorialDraw.setPos(this.position); - } - // Must generate a dynamic space : - setPos(Vector3f(this.position.x() + interpolation, - this.position.y(), - this.position.z()) ); - if( this.needDisplay == true - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM this.colorBg.a() != 0) { - this.vectorialDraw.rectangleWidth(Vector3f(interpolation,fontHeigh,0.0f) ); - } - } else { - //Log.debug(" generateString : \"" + (char)text[iii] + "\""); - if( this.needDisplay == true - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM this.colorBg.a() != 0) { - Vector3f pos = this.position; - this.vectorialDraw.setPos(pos); - printChar(_text[iii]); - this.vectorialDraw.rectangleWidth(Vector3f(this.position.x()-pos.x(),fontHeigh,0.0f) ); - this.nbCharDisplayed++; - } else { - printChar(_text[iii]); - this.nbCharDisplayed++; - } - } - if (this.needDisplay == true) { - if ((long)iii == this.cursorPos-1) { - this.vectorialDraw.setPos(this.position); - setColorBg(this.colorCursor); - printCursor(false); - } - } - } - if (currentId == stop) { - currentId++; - } else if(_text[stop] == u32char::Space) { - currentId = stop+1; - // reset position : - setPos(Vector3f(this.startTextpos, - (float)(this.position.y() - getHeight()), - this.position.z()) ); - this.nbCharDisplayed++; - } else if(_text[stop] == u32char::Return) { - currentId = stop+1; - // reset position : - setPos(Vector3f(this.startTextpos, - (float)(this.position.y() - getHeight()), - this.position.z()) ); - this.nbCharDisplayed++; - } else { - currentId = stop; - } - } - //Log.debug(" 4 print in not alligned mode : start=" + this.sizeDisplayStart + " stop=" + this.sizeDisplayStop + " pos=" + this.position); - } -} - - - - -void ewol::compositing::TextBase::forceLineReturn() { - // reset position : - setPos(Vector3f(this.startTextpos, this.position.y() - getHeight(), 0) ); -} - -void ewol::compositing::TextBase::setTextAlignement(float _startTextpos, float _stopTextPos, enum ewol::compositing::aligneMode _alignement) { - this.startTextpos = _startTextpos; - this.stopTextPos = _stopTextPos+1; - this.alignement = _alignement; - if (this.startTextpos >= this.stopTextPos) { - // TODO: understand why this flush ... - Log.verbose("Request allignement with Borne position error : " + _startTextpos + " => " + _stopTextPos); - } -} - -enum ewol::compositing::aligneMode ewol::compositing::TextBase::getAlignement() { - return this.alignement; -} - -void ewol::compositing::TextBase::disableAlignement() { - this.alignement = alignDisable; -} - -Vector3f ewol::compositing::TextBase::calculateSizeHTML( String _text) { - // remove intermediate result - reset(); - //Log.debug(" 0 size for=\n" + text); - // disable display system - this.needDisplay = false; - - setPos(Vector3f(0,0,0) ); - // same as print without the end display ... - printHTML(_text); - //Log.debug(" 1 Start pos=" + this.sizeDisplayStart); - //Log.debug(" 1 Stop pos=" + this.sizeDisplayStop); - - // get the last elements - this.sizeDisplayStop.setValue(etk::max(this.position.x(), this.sizeDisplayStop.x()) , - etk::max(this.position.y(), this.sizeDisplayStop.y()) , - 0); - this.sizeDisplayStart.setValue(etk::min(this.position.x(), this.sizeDisplayStart.x()) , - etk::min(this.position.y(), this.sizeDisplayStart.y()) , - 0); - - //Log.debug(" 2 Start pos=" + this.sizeDisplayStart); - //Log.debug(" 2 Stop pos=" + this.sizeDisplayStop); - // set back the display system - this.needDisplay = true; - - return Vector3f( this.sizeDisplayStop.x()-this.sizeDisplayStart.x(), - this.sizeDisplayStop.y()-this.sizeDisplayStart.y(), - this.sizeDisplayStop.z()-this.sizeDisplayStart.z()); -} - -Vector3f ewol::compositing::TextBase::calculateSizeHTML( etk::UString _text) { - // remove intermediate result - reset(); - //Log.debug(" 0 size for=\n" + text); - // disable display system - this.needDisplay = false; - - setPos(Vector3f(0,0,0) ); - // same as print without the end display ... - printHTML(_text); - //Log.debug(" 1 Start pos=" + this.sizeDisplayStart); - //Log.debug(" 1 Stop pos=" + this.sizeDisplayStop); - - // get the last elements - this.sizeDisplayStop.setValue(etk::max(this.position.x(), this.sizeDisplayStop.x()) , - etk::max(this.position.y(), this.sizeDisplayStop.y()) , - 0); - this.sizeDisplayStart.setValue(etk::min(this.position.x(), this.sizeDisplayStart.x()) , - etk::min(this.position.y(), this.sizeDisplayStart.y()) , - 0); - - //Log.debug(" 2 Start pos=" + this.sizeDisplayStart); - //Log.debug(" 2 Stop pos=" + this.sizeDisplayStop); - // set back the display system - this.needDisplay = true; - - return Vector3f( this.sizeDisplayStop.x()-this.sizeDisplayStart.x(), - this.sizeDisplayStop.y()-this.sizeDisplayStart.y(), - this.sizeDisplayStop.z()-this.sizeDisplayStart.z()); -} - -Vector3f ewol::compositing::TextBase::calculateSizeDecorated( String _text) { - if (_text.size() == 0) { - return Vector3f(0,0,0); - } - String tmpData("\n"); - tmpData+=_text; - tmpData+="\n\n"; - Vector3f tmpVal = calculateSizeHTML(tmpData); - return tmpVal; -} - -Vector3f ewol::compositing::TextBase::calculateSizeDecorated( etk::UString _text) { - if (_text.size() == 0) { - return Vector3f(0,0,0); - } - etk::UString tmpData(U"\n"); - tmpData += _text; - tmpData += U"\n\n"; - Vector3f tmpVal = calculateSizeHTML(tmpData); - return tmpVal; -} - -Vector3f ewol::compositing::TextBase::calculateSize( String _text) { - Vector3f outputSize(0, 0, 0); - for(auto element : _text) { - Vector3f tmpp = calculateSize(element); - if (outputSize.y() == 0) { - outputSize.setY(tmpp.y()); - } - outputSize.setX( outputSize.x() + tmpp.x()); - } - return outputSize; -} - -Vector3f ewol::compositing::TextBase::calculateSize( etk::UString _text) { - Vector3f outputSize(0, 0, 0); - for(auto element : _text) { - Vector3f tmpp = calculateSize(element); - if (outputSize.y() == 0) { - outputSize.setY(tmpp.y()); - } - outputSize.setX( outputSize.x() + tmpp.x()); - } - return outputSize; -} - -void ewol::compositing::TextBase::printCursor(boolean _isInsertMode, float _cursorSize) { - int fontHeigh = getHeight(); - if (true == _isInsertMode) { - this.vectorialDraw.rectangleWidth(Vector3f(_cursorSize, fontHeigh, 0) ); - } else { - this.vectorialDraw.setThickness(2); - this.vectorialDraw.lineRel( Vector3f(0, fontHeigh, 0) ); - this.vectorialDraw.setThickness(0); - } -} - -boolean ewol::compositing::TextBase::extrapolateLastId( String _text, - int _start, - int _stop, - int _space, - int _freeSpace) { - // store previous : - Character storePrevious = this.previousCharcode; - - _stop = _text.size(); - _space = 0; - - int lastSpacePosition = _start; - int lastSpacefreeSize = 0; - - float endPos = this.position.x(); - boolean endOfLine = false; - - float stopPosition = this.stopTextPos; - if( this.needDisplay == false - || this.stopTextPos == this.startTextpos) { - stopPosition = this.startTextpos + 3999999999.0; - } - - for (int iii=_start; iii<_text.size(); iii++) { - Vector3f tmpSize = calculateSize(_text[iii]); - // check oveflow : - if (endPos + tmpSize.x() > stopPosition) { - _stop = iii; - break; - } - // save number of space : - if ((Character)_text[iii] == u32char::Space) { - _space++; - lastSpacePosition = iii; - lastSpacefreeSize = stopPosition - endPos; - } else if ((Character)_text[iii] == u32char::Return) { - _stop = iii; - endOfLine = true; - break; - } - // update local size : - endPos += tmpSize.x(); - } - _freeSpace = stopPosition - endPos; - // retore previous : - this.previousCharcode = storePrevious; - // need to align left or right ... - if(_stop == (long)_text.size()) { - return true; - } else { - if (endOfLine) { - return true; - } else { - if (_space == 0) { - return true; - } - _stop = lastSpacePosition; - _freeSpace = lastSpacefreeSize; - return false; - } - } -} - -boolean ewol::compositing::TextBase::extrapolateLastId( etk::UString _text, - int _start, - int _stop, - int _space, - int _freeSpace) { - // store previous : - Character storePrevious = this.previousCharcode; - - _stop = _text.size(); - _space = 0; - - int lastSpacePosition = _start; - int lastSpacefreeSize = 0; - - float endPos = this.position.x(); - boolean endOfLine = false; - - float stopPosition = this.stopTextPos; - if( this.needDisplay == false - || this.stopTextPos == this.startTextpos) { - stopPosition = this.startTextpos + 3999999999.0; - } - - for (int iii=_start; iii<_text.size(); iii++) { - Vector3f tmpSize = calculateSize(_text[iii]); - // check oveflow : - if (endPos + tmpSize.x() > stopPosition) { - _stop = iii; - break; - } - // save number of space : - if (_text[iii] == u32char::Space) { - _space++; - lastSpacePosition = iii; - lastSpacefreeSize = stopPosition - endPos; - } else if (_text[iii] == u32char::Return) { - _stop = iii; - endOfLine = true; - break; - } - // update local size : - endPos += tmpSize.x(); - } - _freeSpace = stopPosition - endPos; - // retore previous : - this.previousCharcode = storePrevious; - // need to align left or right ... - if(_stop == (long)_text.size()) { - return true; - } else { - if (endOfLine) { - return true; - } else { - if (_space == 0) { - return true; - } - _stop = lastSpacePosition; - _freeSpace = lastSpacefreeSize; - return false; - } - } -} - -void ewol::compositing::TextBase::htmlAddData( etk::UString _data) { - if( this.htmlCurrrentLine.size()>0 - LOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOMLOM this.htmlCurrrentLine[this.htmlCurrrentLine.size()-1] != ' ') { - this.htmlCurrrentLine += U" "; - if(this.htmlDecoration.size()>0) { - TextDecoration tmp = this.htmlDecoration[this.htmlDecoration.size()-1]; - this.htmlDecoration.pushBack(tmp); - } else { - this.htmlDecoration.pushBack(this.htmlDecoTmp); - } - } - this.htmlCurrrentLine += _data; - for(int iii=0; iii<_data.size() ; iii++) { - this.htmlDecoration.pushBack(this.htmlDecoTmp); - } -} - -void ewol::compositing::TextBase::htmlFlush() { - if (this.htmlCurrrentLine.size()>0) { - print(this.htmlCurrrentLine, this.htmlDecoration); - } - this.htmlCurrrentLine = U""; - this.htmlDecoration.clear(); -} - -void ewol::compositing::TextBase::disableCursor() { - this.selectionStartPos = -100; - this.cursorPos = -100; -} - -void ewol::compositing::TextBase::setCursorPos(int _cursorPos) { - this.selectionStartPos = _cursorPos; - this.cursorPos = _cursorPos; -} - -void ewol::compositing::TextBase::setCursorSelection(int _cursorPos, int _selectionStartPos) { - this.selectionStartPos = _selectionStartPos; - this.cursorPos = _cursorPos; -} - -void ewol::compositing::TextBase::setSelectionColor( etk::Color<> _color) { - this.colorSelection = _color; -} - -void ewol::compositing::TextBase::setCursorColor( etk::Color<> _color) { - this.colorCursor = _color; -} diff --git a/src/org/atriasoft/ewol/compositing/TextBase.java b/src/org/atriasoft/ewol/compositing/TextBase.java index bc85b84..15630af 100644 --- a/src/org/atriasoft/ewol/compositing/TextBase.java +++ b/src/org/atriasoft/ewol/compositing/TextBase.java @@ -3,466 +3,1137 @@ * @copyright 2011, Edouard DUPIN, all right reserved * @license MPL v2.0 (see license file) */ -#pragma once +package org.atriasoft.ewol.compositing; -#include +import java.util.ArrayList; +import java.util.List; -#include#include#include#include#include#include +import org.atriasoft.etk.Color; +import org.atriasoft.etk.Uri; +import org.atriasoft.etk.math.Matrix4f; +import org.atriasoft.etk.math.Vector2f; +import org.atriasoft.etk.math.Vector3f; +import org.atriasoft.ewol.compositing.tools.TextDecoration; +import org.atriasoft.ewol.internal.Log; +import org.atriasoft.ewol.resource.font.FontMode; +import org.atriasoft.ewol.resource.font.GlyphProperty; +import org.atriasoft.exml.Exml; +import org.atriasoft.exml.exception.ExmlAttributeDoesNotExist; +import org.atriasoft.exml.exception.ExmlBuilderException; +import org.atriasoft.exml.exception.ExmlNodeDoesNotExist; +import org.atriasoft.exml.exception.ExmlParserErrorMulti; +import org.atriasoft.exml.model.XmlElement; +import org.atriasoft.exml.model.XmlNode; +import org.atriasoft.gale.resource.ResourceProgram; +import org.atriasoft.gale.resource.ResourceVirtualBufferObject; -namespace ewol{namespace compositing{enum aligneMode { - alignDisable, - alignRight, - alignLeft, - alignCenter, - alignJustify +enum AligneMode { + alignDisable, alignRight, alignLeft, alignCenter, alignJustify }; -class TextBase:public ewol::Compositing -{ - protected: - ewol::compositing::Drawing this.vectorialDraw; //!< This is used to draw background selection and other things ... - public: - ewol::compositing::Drawing getDrawing() { - return this.vectorialDraw; - };protected:int this.nbCharDisplayed; //!< prevent some error in calculation size. - Vector3f this.sizeDisplayStart; //!< The start windows of the display. - Vector3f this.sizeDisplayStop; //!< The end windows of the display. - boolean this.needDisplay; //!< This just need the display and not the size rendering. - Vector3f this.position; //!< The current position to draw - Vector3f this.clippingPosStart; //!< Clipping start position - Vector3f this.clippingPosStop; //!< Clipping stop position - boolean this.clippingEnable; //!< true if the clipping must be activated - protected:etk::Colorthis.defaultColorFg; //!< The text foreground color - etk::Colorthis.defaultColorBg; //!< The text background color - protected:etk::Colorthis.color; //!< The text foreground color - etk::Colorthis.colorBg; //!< The text background color - etk::Colorthis.colorCursor; //!< The text cursor color - etk::Colorthis.colorSelection; //!< The text Selection color - protected: - - enum ewol:: - font:: - mode this.mode; //!< font display property : Regular/Bold/Italic/BoldItalic - boolean this.kerning; //!< Kerning enable or disable on the next elements displayed - Character this.previousCharcode; //!< we remember the previous charcode to perform the kerning. @ref Kerning - protected:float this.startTextpos; //!< start position of the Alignement (when \n the text return at this position) - float this.stopTextPos; //!< end of the alignement (when a string is too hight it cut at the word previously this line and the center is perform with this one) - - enum aligneMode this.alignement; //!< Current Alignement mode (justify/left/right ...) - protected: - ememory::Ptr this.GLprogram; //!< pointer on the opengl display program - int this.GLPosition; //!< openGL id on the element (vertex buffer) - int this.GLMatrix; //!< openGL id on the element (transformation matrix) - int this.GLColor; //!< openGL id on the element (color buffer) - int this.GLtexture; //!< openGL id on the element (Texture position) - int this.GLtexID; //!< openGL id on the element (texture ID) - int this.GLtextWidth; //!< openGL Id on the texture width - int this.GLtextHeight; //!< openGL Id on the texture height - protected: - int this.selectionStartPos; //!< start position of the Selection (if == this.cursorPos ==> no selection) - int this.cursorPos; //!< Cursor position (default no cursor == > -100) - protected: // Text - static int this.vboIdCoord; - static int this.vboIdCoordText; - static int this.vboIdColor; - static int this.vboIdGlyphLevel; - ememory::Ptr this.VBO; - public: - /** - * @brief load the openGL program and get all the ID needed - */ - void loadProgram( String _shaderName); - - public: - /** - * @brief generic ructor - */ - TextBase( final String _shaderName = "DATA:///text.prog?lib=ewol", boolean _loadProgram = true); - /** - * @brief generic destructor - */ - ~TextBase(); - public: // Derived function - - void translate(Vector3f _vect); - - void rotate(Vector3f _vect, float _angle); - - void scale(Vector3f _vect); - - public: - /** - * @brief draw All the refistered text in the current element on openGL - */ - void draw(final boolean _disableDepthTest=true) { - drawD(_disableDepthTest); - } - - //! @previous - void draw( final Matrix4f _transformationMatrix, final boolean _enableDepthTest=false) { - drawMT(_transformationMatrix, _enableDepthTest); - } - - /** - * @brief draw All the refistered text in the current element on openGL - */ - void drawD(final boolean _disableDepthTest) = 0; - //! @previous - void drawMT( final Matrix4f _transformationMatrix, final boolean _enableDepthTest) = 0; - - /** - * @brief clear all the registered element in the current element - */ - void clear(); - - /** - * @brief clear all the intermediate result detween 2 prints - */ - void reset(); - - /** - * @brief get the current display position (sometime needed in the gui control) - * @return the current position. - */ - Vector3f getPos() { - return this.position; - }; - - /** - * @brief set position for the next text writen - * @param[in] _pos Position of the text (in 3D) - */ - void setPos(Vector3f _pos); - - //! @previous - void setPos(final Vector2f _pos) { - setPos(Vector3f(_pos.x(), _pos.y(), 0)); - }; - - /** - * @brief set relative position for the next text writen - * @param[in] _pos ofset apply of the text (in 3D) - */ - void setRelPos(Vector3f _pos); - - //! @previous - void setRelPos(final Vector2f _pos) { - setRelPos(Vector3f(_pos.x(), _pos.y(), 0)); - }; - - /** - * @brief set the default background color of the font (when reset, set this value ...) - * @param[in] _color Color to set on background - */ - void setDefaultColorBg(etk::Color<>_color) {this.defaultColorBg=_color;} - - /** - * @brief set the default Foreground color of the font (when reset, set this value ...) - * @param[in] _color Color to set on foreground - */ - void setDefaultColorFg(etk::Color<>_color) {this.defaultColorFg=_color;} - - /** - * @brief set the Color of the current foreground font - * @param[in] _color Color to set on foreground (for next print) - */ - void setColor( etk::Color<> _color) { - this.color = _color; - }; - - /** - * @brief set the background color of the font (for selected Text (not the global BG)) - * @param[in] _color Color to set on background (for next print) - */ - void setColorBg( etk::Color<> _color); - - /** - * @brief Request a clipping area for the text (next draw only) - * @param[in] _pos Start position of the clipping - * @param[in] _width Width size of the clipping - */ - void setClippingWidth(final Vector3f _pos, final Vector3f _width) { - setClipping(_pos, _pos + _width); +public abstract class TextBase extends Compositing { + private static final int NB_VBO = 4; + // Text + protected static int vboIdCoord = 0; + protected static int vboIdCoordText = 1; + protected static int vboIdColor = 2; + protected static int vboIdGlyphLevel = 3; + // TODO set it back later ... protected CompositingDrawing vectorialDraw; //!< + // This is used to draw background selection and other things ... + /* + * public CompositingDrawing getDrawing() { return //TODO this.vectorialDraw; }; + */ + protected int nbCharDisplayed; // !< prevent some error in calculation size. + protected Vector3f sizeDisplayStart = Vector3f.ZERO; // !< The start windows of the display. + protected Vector3f sizeDisplayStop = Vector3f.ZERO; // !< The end windows of the display. + protected boolean needDisplay; // !< This just need the display and not the size rendering. + protected Vector3f position = Vector3f.ZERO; // !< The current position to draw + protected Vector3f clippingPosStart = Vector3f.ZERO; // !< Clipping start position + protected Vector3f clippingPosStop = Vector3f.ZERO; // !< Clipping stop position + protected boolean clippingEnable = false; // !< true if the clipping must be activated + protected Color defaultColorFg = Color.BLACK; // !< The text foreground color + protected Color defaultColorBg = Color.NONE; // !< The text background color + + protected Color color = Color.BLACK; // !< The text foreground color + protected Color colorBg = Color.NONE; // !< The text background color + protected Color colorCursor = Color.BLACK; // !< The text cursor color + protected Color colorSelection = Color.OLIVE; // !< The text Selection color + protected FontMode mode = FontMode.Regular; // !< font display property : Regular/Bold/Italic/BoldItalic + protected boolean kerning = true; // !< Kerning enable or disable on the next elements displayed + protected Character previousCharcode; // !< we remember the previous charcode to perform the kerning. @ref Kerning + protected float startTextpos = 0; // !< start position of the Alignement (when \n the text return at this + // position) + protected float stopTextPos = 0; // !< end of the alignement (when a string is too hight it cut at the word + // previously this line and the center is perform with this one) + protected AligneMode alignement = AligneMode.alignDisable; // !< Current Alignement mode (justify/left/right ...) + protected ResourceProgram GLprogram; // !< pointer on the opengl display program + protected int GLPosition = -1; // !< openGL id on the element (vertex buffer) + protected int GLMatrix = -1; // !< openGL id on the element (transformation matrix) + protected int GLColor = -1; // !< openGL id on the element (color buffer) + protected int GLtexture = -1; // !< openGL id on the element (Texture position) + protected int GLtexID = -1; // !< openGL id on the element (texture ID) + protected int GLtextWidth = -1; // !< openGL Id on the texture width + protected int GLtextHeight = -1; // !< openGL Id on the texture height + protected int selectionStartPos = -100; // !< start position of the Selection (if == this.cursorPos ==> no + // selection) + protected int cursorPos = -100; // !< Cursor position (default no cursor == > -100) + protected ResourceVirtualBufferObject VBO; + // this section is reserved for HTML parsing and display: + public String htmlCurrrentLine = ""; // !< current line for HTML display + public List htmlDecoration = new ArrayList<>(); // !< current decoration for the HTML display + public TextDecoration htmlDecoTmp = new TextDecoration(); // !< current decoration + + /** + * @brief generic constructor + */ + public TextBase() { + this(new Uri("DATA", "text.vert", "ewol"), new Uri("DATA", "text.frag", "ewol")); + } + + public TextBase(final Uri _vertexShader, final Uri _fragmentShader) { + this(_vertexShader, _fragmentShader, true); + } + + public TextBase(final Uri _vertexShader, final Uri _fragmentShader, final boolean _loadProgram) { + if (_loadProgram == true) { + loadProgram(_vertexShader, _fragmentShader); + } + // Create the VBO: + this.VBO = ResourceVirtualBufferObject.create(NB_VBO); + if (this.VBO == null) { + Log.error("can not instanciate VBO ..."); + return; + } + // TO facilitate some debugs we add a name of the VBO: + this.VBO.setName("[VBO] of super.TextBase"); + } + + /** + * @brief calculate a theoric charcode size + * @param[in] _charcode The Unicode value to calculate dimention. + * @return The theoric size used. + */ + public Vector3f calculateSize(final Character _charcode) { + return calculateSizeChar(_charcode); + } + + /** + * @brief calculate a theoric text size + * @param[in] _text The string to calculate dimention. + * @return The theoric size used. + */ + public Vector3f calculateSize(final String _text) { + Vector3f outputSize = Vector3f.ZERO; + for (int iii = 0; iii < _text.length(); iii++) { + Vector3f tmpp = calculateSize(_text.charAt(iii)); + if (outputSize.y() == 0) { + outputSize = outputSize.withY(tmpp.y()); } - - //! @previous - void setClippingWidth(final Vector2f _pos, final Vector2f _width) { - setClipping(_pos, _pos + _width); - }; - - /** - * @brief Request a clipping area for the text (next draw only) - * @param[in] _pos Start position of the clipping - * @param[in] _posEnd End position of the clipping - */ - void setClipping(Vector3f _pos, Vector3f _posEnd); - - //! @previous - void setClipping(final Vector2f _pos, final Vector2f _posEnd) { - setClipping(Vector3f(_pos.x(), _pos.y(), -1), Vector3f(_posEnd.x(), _posEnd.y(), 1)); - }; - - /** - * @brief enable/Disable the clipping (without lose the current clipping position) - * @brief _newMode The new status of the clipping - */ - // TODO : Rename setClippingActivity - void setClippingMode(boolean _newMode); - - /** - * @brief Specify the font size (this reset the internal element of the current text (system requirement) - * @param[in] _fontSize New font size - */ - void setFontSize(final int _fontSize) = 0; - - /** - * @brief Specify the font name (this reset the internal element of the current text (system requirement) - * @param[in] _fontName Current name of the selected font - */ - void setFontName( final String _fontName) = 0; - - /** - * @brief Specify the font property (this reset the internal element of the current text (system requirement) - * @param[in] fontName Current name of the selected font - * @param[in] fontSize New font size - */ - void setFont(final String _fontName, final int _fontSize) = 0; - - /** - * @brief Specify the font mode for the next @ref print - * @param[in] mode The font mode requested - */ - void setFontMode(enum ewol::font::mode _mode)=0; - /** - * @brief get the current font mode - * @return The font mode applied - */ - enum ewol::font::mode getFontMode(){return this.mode;};float getHeight()=0;float getSize()=0;ewol::GlyphProperty*getGlyphPointer(Character _charcode)=0; - /** - * @brief enable or disable the bold mode - * @param[in] _status The new status for this display property - */ - void setFontBold(boolean _status); - /** - * @brief enable or disable the italic mode - * @param[in] _status The new status for this display property - */ - void setFontItalic(boolean _status); - /** - * @brief set the activation of the Kerning for the display (if it existed) - * @param[in] _newMode enable/Diasable the kerning on this font. - */ - void setKerningMode(boolean _newMode); - /** - * @brief display a compleat string in the current element. - * @param[in] _text The string to display. - */ - void print(String _text); - //! @previous - void print(etk::UString _text); - /** - * @brief display a compleat string in the current element with the generic decoration specification. (basic html data) - * - * [code style=xml] - *
- *


- *
- * text exemple in bold other text bold part boldItalic part an other thext - * colored text bold color text bold italic text normal color text the end of the string
- * an an other thext - *
- *


- * - * plop 1 - * - *


- * - * plop 2 - * - *


- * - * Un exemple de text - * - * [/code] - * - * @note This is parsed with tiny xml, then be carfull that the XML is correct, and all balises are closed ... otherwite the display can not be done - * @param[in] _text The string to display. - * @TODO : implementation not done .... - */ - void printDecorated(String _text); - //! @previous - void printDecorated(etk::UString _text); - /** - * @brief display a compleat string in the current element with the generic decoration specification. (basic html data) - * - * [code style=xml] - * - * - *
- *


- *
- * text exemple in bold other text bold part boldItalic part an other thext - * colored text bold color text bold italic text normal color text the end of the string
- * an an other thext - *
- *


- * - * plop 1 - * - *


- * - * plop 2 - * - *


- * - * Un exemple de text - * - * - * - * [/code] - * - * @note This is parsed with tiny xml, then be carfull that the XML is correct, and all balises are closed ... otherwite the display can not be done - * @param[in] _text The string to display. - * @TODO : implementation not done .... - */ - void printHTML(String _text); - //! @previous - void printHTML(etk::UString _text); - /** - * @brief display a compleat string in the current element whith specific decorations (advence mode). - * @param[in] _text The string to display. - * @param[in] _decoration The text decoration for the text that might be display (if the vector is smaller, the last parameter is get) - */ - void print(String _text,List_decoration); - //! @previous - void print(etk::UString _text,List_decoration); - /** - * @brief display the current char in the current element (note that the kerning is availlable if the position is not changed) - * @param[in] _charcode Char that might be dispalyed - */ - void printChar(Character _charcode)=0; - /** - * @brief This generate the line return == > it return to the alignement position start and at the correct line position ==> it might be use to not know the line height - */ - void forceLineReturn();protected: - /** - * @brief This parse a tinyXML node (void pointer to permit to hide tiny XML in include). - * @param[in] _element the exml element. - */ - void parseHtmlNode(exml::Element _element);public: - /** - * @brief This generate the possibility to generate the big text property - * @param[in] _startTextpos The x text start position of the display. - * @param[in] _stopTextPos The x text stop position of the display. - * @param[in] _alignement mode of alignement for the Text. - * @note The text align in center change of line every display done (even if it was just a char) - */ - void setTextAlignement(float _startTextpos,float _stopTextPos,enum ewol::compositing::aligneMode _alignement=ewol::compositing::alignDisable); - /** - * @brief disable the alignement system - */ - void disableAlignement(); - /** - * @brief get the current alignement property - * @return the curent alignement type - */ - enum ewol::compositing::aligneMode getAlignement(); - /** - * @brief calculate a theoric text size - * @param[in] _text The string to calculate dimention. - * @return The theoric size used. - */ - Vector3f calculateSizeHTML(String _text); - //! @previous - Vector3f calculateSizeHTML(etk::UString _text); - /** - * @brief calculate a theoric text size - * @param[in] _text The string to calculate dimention. - * @return The theoric size used. - */ - Vector3f calculateSizeDecorated(String _text); - //! @previous - Vector3f calculateSizeDecorated(etk::UString _text); - /** - * @brief calculate a theoric text size - * @param[in] _text The string to calculate dimention. - * @return The theoric size used. - */ - Vector3f calculateSize(String _text); - //! @previous - Vector3f calculateSize(etk::UString _text); - /** - * @brief calculate a theoric charcode size - * @param[in] _charcode The Unicode value to calculate dimention. - * @return The theoric size used. - */ - Vector3f calculateSize(Character _charcode){return calculateSizeChar(_charcode);};protected: - //! @previous - Vector3f calculateSizeChar(Character _charcode)=0;public: - /** - * @brief draw a cursor at the specify position - * @param[in] _isInsertMode True if the insert mode is activated - * @param[in] _cursorSize The sizae of the cursor that might be set when insert mode is set [default 20] - */ - void printCursor(boolean _isInsertMode,float _cursorSize=20.0f);protected: - /** - * @brief calculate the element number that is the first out the alignement range - * (start at the specify ID, and use start pos with current one) - * @param[in] _text The string that might be parsed. - * @param[in] _start The first elemnt that might be used to calculate. - * @param[out] _stop The last Id availlable in the current string. - * @param[out] _space Number of space in the string. - * @param[out] _freespace This represent the number of pixel present in the right white space. - * @return true if the rifht has free space that can be use for jystify. - * @return false if we find '\n' - */ - boolean extrapolateLastId(String _text,int _start,int _stop,int _space,int _freeSpace); - //! @previous - boolean extrapolateLastId(etk::UString _text,int _start,int _stop,int _space,int _freeSpace);protected: - // this section is reserved for HTML parsing and display: - etk::UString this.htmlCurrrentLine; //!< current line for HTML display - Listthis.htmlDecoration; //!< current decoration for the HTML display - TextDecoration this.htmlDecoTmp; //!< current decoration - /** - * @brief add a line with the current this.htmlDecoTmp decoration - * @param[in] _data The cuurent data to add. - */ - void htmlAddData(etk::UString _data); - /** - * @brief draw the current line - */ - void htmlFlush();public: - /** - * @brief remove the cursor display - */ - void disableCursor(); - /** - * @brief set a cursor at a specific position: - * @param[in] _cursorPos id of the cursor position - */ - void setCursorPos(int _cursorPos); - /** - * @brief set a cursor at a specific position with his associated selection: - * @param[in] _cursorPos id of the cursor position - * @param[in] _selectionStartPos id of the starting of the selection - */ - void setCursorSelection(int _cursorPos,int _selectionStartPos); - /** - * @brief change the selection color - * @param[in] _color New color for the Selection - */ - void setSelectionColor(etk::Color<>_color); - /** - * @brief change the cursor color - * @param[in] _color New color for the Selection - */ - void setCursorColor(etk::Color<>_color);};}} - - ; - - /** - * @brief This class represent the specific display for every char in the string ... - * @not_in_doc - */ - class TextDecoration{ + outputSize = outputSize.withX(outputSize.x() + tmpp.x()); + } + return outputSize; + } + + // ! @previous + public abstract Vector3f calculateSizeChar(Character _charcode); + + /** + * @brief calculate a theoric text size + * @param[in] _text The string to calculate dimention. + * @return The theoric size used. + */ + public Vector3f calculateSizeDecorated(final String _text) { + if (_text.length() == 0) { + return Vector3f.ZERO; + } + + String tmpData = "\n"; + tmpData += _text; + tmpData += "\n\n"; + Vector3f tmpVal = calculateSizeHTML(tmpData); + return tmpVal; + } + + /** + * @brief calculate a theoric text size + * @param[in] _text The string to calculate dimention. + * @return The theoric size used. + */ + public Vector3f calculateSizeHTML(final String _text) { + // remove intermediate result + reset(); + // Log.debug(" 0 size for=\n" + text); + // disable display system + this.needDisplay = false; + + setPos(Vector3f.ZERO); + // same as print without the end display ... + printHTML(_text); + // Log.debug(" 1 Start pos=" + this.sizeDisplayStart); + // Log.debug(" 1 Stop pos=" + this.sizeDisplayStop); + + // get the last elements + this.sizeDisplayStop = Vector3f.max(this.position, this.sizeDisplayStop); + this.sizeDisplayStart = Vector3f.min(this.position, this.sizeDisplayStop); + + // Log.debug(" 2 Start pos=" + this.sizeDisplayStart); + // Log.debug(" 2 Stop pos=" + this.sizeDisplayStop); + // set back the display system + this.needDisplay = true; + + return new Vector3f(this.sizeDisplayStop.x() - this.sizeDisplayStart.x(), + this.sizeDisplayStop.y() - this.sizeDisplayStart.y(), + this.sizeDisplayStop.z() - this.sizeDisplayStart.z()); + } + + /** + * @brief clear all the registered element in the current element + */ + @Override + public void clear() { + // call upper class + super.clear(); + // remove sub draw system + // TODO this.vectorialDraw.clear(); + // reset Buffer: + this.VBO.clear(); + // reset temporal variables: + reset(); + } + + /** + * @brief disable the alignement system + */ + public void disableAlignement() { + this.alignement = AligneMode.alignDisable; + } + + /** + * @brief remove the cursor display + */ + public void disableCursor() { + this.selectionStartPos = -100; + this.cursorPos = -100; + } + + /** + * @brief draw All the registered text in the current element on openGL + */ + @Override + public void draw(final boolean _disableDepthTest) { + drawD(_disableDepthTest); + } + + // ! @previous + public void draw(final Matrix4f _transformationMatrix, final boolean _enableDepthTest) { + drawMT(_transformationMatrix, _enableDepthTest); + } + + /** + * @brief draw All the refistered text in the current element on openGL + */ + public abstract void drawD(final boolean _disableDepthTest);; + + // ! @previous + public abstract void drawMT(final Matrix4f _transformationMatrix, final boolean _enableDepthTest); + + /** + * @brief calculate the element number that is the first out the alignement + * range (start at the specify ID, and use start pos with current one) + * @param[in] _text The string that might be parsed. + * @param[in] _start The first elemnt that might be used to calculate. + * @param[out] _stop The last Id availlable in the current string. + * @param[out] _space Number of space in the string. + * @param[out] _freespace This represent the number of pixel present in the + * right white space. + * @return true if the rifht has free space that can be use for jystify. + * @return false if we find '\n' + */ + public boolean extrapolateLastId(final String _text, final int _start, int _stop, int _space, int _freeSpace) { + // store previous : + Character storePrevious = this.previousCharcode; + + _stop = _text.length(); + _space = 0; + + int lastSpacePosition = _start; + int lastSpacefreeSize = 0; + + float endPos = this.position.x(); + boolean endOfLine = false; + + float stopPosition = this.stopTextPos; + if (this.needDisplay == false || this.stopTextPos == this.startTextpos) { + stopPosition = this.startTextpos + 3999999999.0f; + } + + for (int iii = _start; iii < _text.length(); iii++) { + Vector3f tmpSize = calculateSize(_text.charAt(iii)); + // check oveflow : + if (endPos + tmpSize.x() > stopPosition) { + _stop = iii; + break; + } + // save number of space : + if (_text.charAt(iii) == Character.SPACE_SEPARATOR) { + _space++; + lastSpacePosition = iii; + lastSpacefreeSize = (int) (stopPosition - endPos); + } else if (_text.charAt(iii) == Character.LINE_SEPARATOR) { + _stop = iii; + endOfLine = true; + break; + } + // update local size : + endPos += tmpSize.x(); + } + _freeSpace = (int) (stopPosition - endPos); + // retore previous : + this.previousCharcode = storePrevious; + // need to align left or right ... + if (_stop == (long) _text.length()) { + return true; + } else { + if (endOfLine) { + return true; + } else { + if (_space == 0) { + return true; + } + _stop = lastSpacePosition; + _freeSpace = lastSpacefreeSize; + return false; + } + } + }; + + /** + * @brief This generate the line return == > it return to the alignement + * position start and at the correct line position ==> it might be use to + * not know the line height + */ + public void forceLineReturn() { + // reset position : + setPos(new Vector3f(this.startTextpos, this.position.y() - getHeight(), 0)); + } + + /** + * @brief get the current alignement property + * @return the curent alignement type + */ + public AligneMode getAlignement() { + return this.alignement; + }; + + /** + * @brief get the current font mode + * @return The font mode applied + */ + public FontMode getFontMode() { + return this.mode; + } + + public abstract GlyphProperty getGlyphPointer(Character _charcode); + + public abstract float getHeight();; + + /** + * @brief get the current display position (sometime needed in the gui control) + * @return the current position. + */ + public Vector3f getPos() { + return this.position; + } + + public abstract float getSize(); + + /** + * @brief add a line with the current this.htmlDecoTmp decoration + * @param[in] _data The cuurent data to add. + */ + public void htmlAddData(final String _data) { + if (this.htmlCurrrentLine.length() > 0 + && this.htmlCurrrentLine.charAt(this.htmlCurrrentLine.length() - 1) != Character.SPACE_SEPARATOR) { + this.htmlCurrrentLine += Character.SPACE_SEPARATOR; + if (this.htmlDecoration.size() > 0) { + TextDecoration tmp = this.htmlDecoration.get(this.htmlDecoration.size() - 1); + this.htmlDecoration.add(tmp); + } else { + this.htmlDecoration.add(this.htmlDecoTmp); + } + } + this.htmlCurrrentLine += _data; + for (int iii = 0; iii < _data.length(); iii++) { + this.htmlDecoration.add(this.htmlDecoTmp); + } + }; + + /** + * @brief draw the current line + */ + public void htmlFlush() { + if (this.htmlCurrrentLine.length() > 0) { + print(this.htmlCurrrentLine, this.htmlDecoration); + } + this.htmlCurrrentLine = ""; + this.htmlDecoration.clear(); + } + + /** + * @brief load the openGL program and get all the ID needed + */ + public void loadProgram(final Uri _vertexShader, final Uri _fragmentShader) { + ResourceProgram old = this.GLprogram; + this.GLprogram = ResourceProgram.create(_vertexShader, _fragmentShader); + if (this.GLprogram != null) { + this.GLPosition = this.GLprogram.getAttribute("EW_coord3d"); + this.GLColor = this.GLprogram.getAttribute("EW_color"); + this.GLtexture = this.GLprogram.getAttribute("EW_texture2d"); + this.GLMatrix = this.GLprogram.getUniform("EW_MatrixTransformation"); + this.GLtexID = this.GLprogram.getUniform("EW_texID"); + this.GLtextWidth = this.GLprogram.getUniform("EW_texWidth"); + this.GLtextHeight = this.GLprogram.getUniform("EW_texHeight"); + } else { + Log.error("Can not load the program => create previous one..."); + this.GLprogram = old; + old = null; + } + }; + + /** + * @brief This parse a tinyXML node (void pointer to permit to hide tiny XML in + * include). + * @param[in] _element the exml element. + */ + public void parseHtmlNode(final XmlElement _element) { + for (XmlNode it : _element.getNodes()) { + if (it.isComment() == true) { + // nothing to do ... + continue; + } else if (it.isText() == true) { + htmlAddData(it.getValue()); + Log.verbose("XML add : " + it.getValue()); + continue; + } else if (it.isElement() == false) { + Log.error("node not suported type : " + it.getType() + " val='" + it.getValue() + "'"); + continue; + } + XmlElement elem = (XmlElement) it; + String lowercaseValue = elem.getValue().toLowerCase(); + if (lowercaseValue.contentEquals("br") == true) { + htmlFlush(); + Log.verbose("XML flush newLine"); + forceLineReturn(); + } else if (lowercaseValue.contentEquals("font") == true) { + Log.verbose("XML Font ..."); + TextDecoration tmpDeco = this.htmlDecoTmp; + if (elem.existAttribute("color")) { + try { + String colorValue = elem.getAttribute("color"); + if (colorValue.length() != 0) { + this.htmlDecoTmp = this.htmlDecoTmp.withFG(Color.valueOf(colorValue)); + } + } catch (ExmlAttributeDoesNotExist e) { + Log.error("Can not get attribute 'color' in XML:" + e.getMessage()); + e.printStackTrace(); + } catch (Exception e) { + Log.error("Can not parse attribute 'color' in XML:" + e.getMessage()); + e.printStackTrace(); + } + } + if (elem.existAttribute("colorBg")) { + try { + String colorValue = elem.getAttribute("colorBg"); + if (colorValue.length() != 0) { + this.htmlDecoTmp = this.htmlDecoTmp.withBG(Color.valueOf(colorValue)); + } + } catch (ExmlAttributeDoesNotExist e) { + Log.error("Can not get attribute 'colorBg' in XML:" + e.getMessage()); + e.printStackTrace(); + } catch (Exception e) { + Log.error("Can not parse attribute 'colorBg' in XML:" + e.getMessage()); + e.printStackTrace(); + } + } + parseHtmlNode(elem); + this.htmlDecoTmp = tmpDeco; + } else if (lowercaseValue.contentEquals("b") == true || lowercaseValue.contentEquals("bold") == true) { + Log.verbose("XML bold ..."); + TextDecoration tmpDeco = this.htmlDecoTmp; + if (this.htmlDecoTmp.mode() == FontMode.Regular) { + this.htmlDecoTmp = this.htmlDecoTmp.withMode(FontMode.Bold); + } else if (this.htmlDecoTmp.mode() == FontMode.Italic) { + this.htmlDecoTmp = this.htmlDecoTmp.withMode(FontMode.BoldItalic); + } + parseHtmlNode(elem); + this.htmlDecoTmp = tmpDeco; + } else if (lowercaseValue.contentEquals("i") == true || lowercaseValue.contentEquals("italic") == true) { + Log.verbose("XML italic ..."); + TextDecoration tmpDeco = this.htmlDecoTmp; + if (this.htmlDecoTmp.mode() == FontMode.Regular) { + this.htmlDecoTmp = this.htmlDecoTmp.withMode(FontMode.Italic); + } else if (this.htmlDecoTmp.mode() == FontMode.Bold) { + this.htmlDecoTmp = this.htmlDecoTmp.withMode(FontMode.BoldItalic); + } + parseHtmlNode(elem); + this.htmlDecoTmp = tmpDeco; + } else if (lowercaseValue.contentEquals("u") == true || lowercaseValue.contentEquals("underline") == true) { + Log.verbose("XML underline ..."); + parseHtmlNode(elem); + } else if (lowercaseValue.contentEquals("p") == true || lowercaseValue.contentEquals("paragraph") == true) { + Log.verbose("XML paragraph ..."); + htmlFlush(); + this.alignement = AligneMode.alignLeft; + forceLineReturn(); + parseHtmlNode(elem); + forceLineReturn(); + } else if (lowercaseValue.contentEquals("center") == true) { + Log.verbose("XML center ..."); + htmlFlush(); + this.alignement = AligneMode.alignCenter; + parseHtmlNode(elem); + } else if (lowercaseValue.contentEquals("left") == true) { + Log.verbose("XML left ..."); + htmlFlush(); + this.alignement = AligneMode.alignLeft; + parseHtmlNode(elem); + } else if (lowercaseValue.contentEquals("right") == true) { + Log.verbose("XML right ..."); + htmlFlush(); + this.alignement = AligneMode.alignRight; + parseHtmlNode(elem); + } else if (lowercaseValue.contentEquals("justify") == true) { + Log.verbose("XML justify ..."); + htmlFlush(); + this.alignement = AligneMode.alignJustify; + parseHtmlNode(elem); + } else { + Log.error("node not suported type: " + elem.getType() + " val='" + elem.getValue() + "'"); + } + } + } + + /** + * @brief display a compleat string in the current element. + * @param[in] _text The string to display. + */ + public void print(final String _text) { + List decorationEmpty = new ArrayList<>(); + print(_text, decorationEmpty); + } + + /** + * @brief display a compleat string in the current element whith specific + * decorations (advence mode). + * @param[in] _text The string to display. + * @param[in] _decoration The text decoration for the text that might be display + * (if the vector is smaller, the last parameter is get) + */ + public void print(final String _text, final List _decoration) { + Color tmpFg = this.color; + Color tmpBg = this.colorBg; + if (this.alignement == AligneMode.alignDisable) { + // Log.debug(" 1 print in not alligned mode : start=" + this.sizeDisplayStart + + // " stop=" + this.sizeDisplayStop + " pos=" + this.position); + // display the cursor if needed (if it is at the start position...) + if (this.needDisplay == true) { + if (0 == this.cursorPos) { + // TODO this.vectorialDraw.setPos(this.position); + setColorBg(this.colorCursor); + printCursor(false); + } + } + // note this is faster when nothing is requested ... + for (int iii = 0; iii < _text.length(); iii++) { + // check if ve have decoration + if (iii < _decoration.size()) { + tmpFg = _decoration.get(iii).colorFG(); + tmpBg = _decoration.get(iii).colorBG(); + setFontMode(_decoration.get(iii).mode()); + } + // if real display : ( not display is for size calculation) + if (this.needDisplay == true) { + if ((this.selectionStartPos - 1 < (long) iii && (long) iii <= this.cursorPos - 1) + || (this.selectionStartPos - 1 >= (long) iii && (long) iii > this.cursorPos - 1)) { + setColor(Color.BLACK); + setColorBg(this.colorSelection); + } else { + setColor(tmpFg); + setColorBg(tmpBg); + } + } + if (this.needDisplay == true && this.colorBg.a() != 0) { + Vector3f pos = this.position; + // TODO this.vectorialDraw.setPos(pos); + printChar(_text.charAt(iii)); + float fontHeigh = getHeight(); + // TODO + // this.vectorialDraw.rectangleWidth(Vector3f(this.position.x()-pos.x(),fontHeigh,0.0f) + // ); + this.nbCharDisplayed++; + } else { + printChar(_text.charAt(iii)); + this.nbCharDisplayed++; + } + // display the cursor if needed (if it is at the other position...) + if (this.needDisplay == true) { + if ((long) iii == this.cursorPos - 1) { + // TODO this.vectorialDraw.setPos(this.position); + setColorBg(this.colorCursor); + printCursor(false); + } + } + } + // Log.debug(" 2 print in not alligned mode : start=" + this.sizeDisplayStart + + // " stop=" + this.sizeDisplayStop + " pos=" + this.position); + } else { + // Log.debug(" 3 print in not alligned mode : start=" + this.sizeDisplayStart + + // " stop=" + this.sizeDisplayStop + " pos=" + this.position); + // special start case at the right of the endpoint : + if (this.stopTextPos < this.position.x()) { + forceLineReturn(); + } + float basicSpaceWidth = calculateSize(' ').x(); + int currentId = 0; + int stop = 0; + int space = 0; + int freeSpace = 0; + while (currentId < (long) _text.length()) { + boolean needNoJustify = extrapolateLastId(_text, currentId, stop, space, freeSpace); + float interpolation = basicSpaceWidth; + switch (this.alignement) { + case alignJustify: + if (needNoJustify == false) { + interpolation += (float) freeSpace / (float) (space - 1); + } + break; + case alignDisable: // must not came from here ... + case alignLeft: + // nothing to do ... + break; + case alignRight: + if (this.needDisplay == true) { + // Move the first char at the right : + setPos(new Vector3f(this.position.x() + freeSpace, this.position.y(), this.position.z())); + } + break; + case alignCenter: + if (this.needDisplay == true) { + // Move the first char at the right : + setPos(new Vector3f(this.position.x() + freeSpace / 2, this.position.y(), this.position.z())); + } + break; + } + // display all the elements + if (this.needDisplay == true && this.cursorPos == 0) { + // TODO this.vectorialDraw.setPos(this.position); + setColorBg(this.colorCursor); + printCursor(false); + } + for (int iii = currentId; (long) iii < stop && iii < _text.length(); iii++) { + float fontHeigh = getHeight(); + // get specific decoration if provided + if (iii < _decoration.size()) { + tmpFg = _decoration.get(iii).colorFG(); + tmpBg = _decoration.get(iii).colorBG(); + setFontMode(_decoration.get(iii).mode()); + } + if (this.needDisplay == true) { + if ((this.selectionStartPos - 1 < (long) iii && (long) iii <= this.cursorPos - 1) + || (this.selectionStartPos - 1 >= (long) iii && (long) iii > this.cursorPos - 1)) { + setColor(Color.BLACK); + setColorBg(this.colorSelection); + } else { + setColor(tmpFg); + setColorBg(tmpBg); + } + } + // special for the justify mode + if (_text.charAt(iii) == Character.SPACE_SEPARATOR) { + // Log.debug(" generateString : \" \""); + if (this.needDisplay == true && this.colorBg.a() != 0) { + // TODO this.vectorialDraw.setPos(this.position); + } + // Must generate a dynamic space : + setPos(new Vector3f(this.position.x() + interpolation, this.position.y(), this.position.z())); + if (this.needDisplay == true && this.colorBg.a() != 0) { + // TODO this.vectorialDraw.rectangleWidth(Vector3f(interpolation,fontHeigh,0.0f) + // ); + } + } else { + // Log.debug(" generateString : \"" + (char)text[iii] + "\""); + if (this.needDisplay == true && this.colorBg.a() != 0) { + Vector3f pos = this.position; + // TODO this.vectorialDraw.setPos(pos); + printChar(_text.charAt(iii)); + // TODO + // this.vectorialDraw.rectangleWidth(Vector3f(this.position.x()-pos.x(),fontHeigh,0.0f) + // ); + this.nbCharDisplayed++; + } else { + printChar(_text.charAt(iii)); + this.nbCharDisplayed++; + } + } + if (this.needDisplay == true) { + if ((long) iii == this.cursorPos - 1) { + // TODO this.vectorialDraw.setPos(this.position); + setColorBg(this.colorCursor); + printCursor(false); + } + } + } + if (currentId == stop) { + currentId++; + } else if (_text.charAt(stop) == Character.SPACE_SEPARATOR) { + currentId = stop + 1; + // reset position : + setPos(new Vector3f(this.startTextpos, this.position.y() - getHeight(), this.position.z())); + this.nbCharDisplayed++; + } else if (_text.charAt(stop) == Character.LINE_SEPARATOR) { + currentId = stop + 1; + // reset position : + setPos(new Vector3f(this.startTextpos, this.position.y() - getHeight(), this.position.z())); + this.nbCharDisplayed++; + } else { + currentId = stop; + } + } + // Log.debug(" 4 print in not alligned mode : start=" + this.sizeDisplayStart + + // " stop=" + this.sizeDisplayStop + " pos=" + this.position); + } + } + + /** + * @brief display the current char in the current element (note that the kerning + * is availlable if the position is not changed) + * @param[in] _charcode Char that might be dispalyed + */ + public abstract void printChar(Character _charcode); + + /** + * @brief draw a cursor at the specify position + * @param[in] _isInsertMode True if the insert mode is activated + * @param[in] _cursorSize The sizae of the cursor that might be set when insert + * mode is set [default 20] + */ + public void printCursor(final boolean _isInsertMode) { + printCursor(_isInsertMode, 20.0f); + } + + public void printCursor(final boolean _isInsertMode, final float _cursorSize) { + int fontHeigh = (int) getHeight(); + if (true == _isInsertMode) { + // TODO this.vectorialDraw.rectangleWidth(Vector3f(_cursorSize, fontHeigh, 0) ); + } else { + // TODO this.vectorialDraw.setThickness(2); + // TODO this.vectorialDraw.lineRel( Vector3f(0, fontHeigh, 0) ); + // TODO this.vectorialDraw.setThickness(0); + } + }; + + /** + * @brief display a compleat string in the current element with the generic + * decoration specification. (basic html data) + * + * [code style=xml]
+ *
+ *
+ *
+ *
text exemple in bold other text bold part + * boldItalic part an other thext + * colored text bold color text bold + * italic text normal color text the end of the string
+ * an an other thext

+ *
+ *
+ * plop 1
+ *
+ *
+ * plop 2
+ *
+ *
+ * Un exemple de text [/code] + * + * @note This is parsed with tiny xml, then be carfull that the XML is correct, + * and all balises are closed ... otherwite the display can not be done + * @param[in] _text The string to display. + * @TODO : implementation not done .... + */ + public void printDecorated(final String _text) { + String tmpData = "\n\n"; + tmpData += _text; + tmpData += "\n\n\n"; + // Log.debug("plop : " + tmpData); + printHTML(tmpData); + } + + /** + * @brief display a compleat string in the current element with the generic + * decoration specification. (basic html data) + * + * [code style=xml]
+ *
+ *
+ *
+ *
text exemple in bold other text bold part + * boldItalic part an other thext + * colored text bold color text bold + * italic text normal color text the end of the string
+ * an an other thext

+ *
+ *
+ * plop 1
+ *
+ *
+ * plop 2
+ *
+ *
+ * Un exemple de text [/code] + * + * @note This is parsed with tiny xml, then be carfull that the XML is correct, + * and all balises are closed ... otherwite the display can not be done + * @param[in] _text The string to display. + * @TODO : implementation not done .... + */ + public void printHTML(final String _text) { + // reset parameter : + this.htmlDecoTmp = new TextDecoration(this.defaultColorFg, this.defaultColorBg, FontMode.Regular); + try { + XmlElement doc = Exml.parse(_text); + if (doc.existNode("html") == false) { + Log.error("can not load XML: main node not find: 'html'"); + Exml.display(doc); + return; + } + XmlElement root = (XmlElement) doc.getNode("html"); + + if (root.existNode("body") == false) { + Log.error("can not load XML: main node not find: 'body'"); + return; + } + XmlElement bodyNode = (XmlElement) root.getNode("body"); + parseHtmlNode(bodyNode); + htmlFlush(); + } catch (ExmlParserErrorMulti e) { + Log.error("Can not parse XML data in printHTML:" + e.getMessage()); + e.printStackTrace(); + } catch (ExmlBuilderException e) { + Log.error("Can not generate XML data in printHTML:" + e.getMessage()); + e.printStackTrace(); + } catch (ExmlNodeDoesNotExist e) { + Log.error("Error in finding node from XML data in printHTML:" + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * @brief clear all the intermediate result detween 2 prints + */ + public void reset() { + this.position = Vector3f.ZERO; + this.clippingPosStart = Vector3f.ZERO; + this.clippingPosStop = Vector3f.ZERO; + this.sizeDisplayStart = this.position; + this.sizeDisplayStop = this.position; + this.nbCharDisplayed = 0; + this.clippingEnable = false; + this.color = this.defaultColorFg; + this.colorBg = this.defaultColorBg; + this.mode = FontMode.Regular; + this.previousCharcode = 0; + this.startTextpos = 0; + this.stopTextPos = 0; + this.alignement = AligneMode.alignDisable; + this.htmlCurrrentLine = ""; + this.selectionStartPos = -100; + this.cursorPos = -100; + this.htmlDecoration.clear(); + this.needDisplay = true; + this.nbCharDisplayed = 0; + } + + @Override + public void rotate(final Vector3f _vect, final float _angle) { + super.rotate(_vect, _angle); + // TODO this.vectorialDraw.rotate(_vect,_angle); + } + + @Override + public void scale(final Vector3f _vect) { + super.scale(_vect); + // TODO this.vectorialDraw.scale(_vect); + } + + // ! @previous + public void setClipping(final Vector2f _pos, final Vector2f _posEnd) { + setClipping(new Vector3f(_pos.x(), _pos.y(), -1), new Vector3f(_posEnd.x(), _posEnd.y(), 1)); + } + + /** + * @brief Request a clipping area for the text (next draw only) + * @param[in] _pos Start position of the clipping + * @param[in] _posEnd End position of the clipping + */ + public void setClipping(final Vector3f _pos, final Vector3f _posEnd) { + // note the internal system all time request to have a bounding all time in the + // same order + this.clippingPosStop = Vector3f.max(_pos, _posEnd); + this.clippingPosStart = Vector3f.min(_pos, _posEnd); + this.clippingEnable = true; + // //TODO this.vectorialDraw.setClipping(this.clippingPosStart, + // this.clippingPosStop); + } + + /** + * @brief enable/Disable the clipping (without lose the current clipping + * position) + * @brief _newMode The new status of the clipping + */ + // TODO : Rename setClippingActivity + public void setClippingMode(final boolean _newMode) { + this.clippingEnable = _newMode; + // //TODO this.vectorialDraw.setClippingMode(this.clippingEnable); + } + + // ! @previous + public void setClippingWidth(final Vector2f _pos, final Vector2f _width) { + setClipping(_pos, _pos.add(_width)); + } + + /** + * @brief Request a clipping area for the text (next draw only) + * @param[in] _pos Start position of the clipping + * @param[in] _width Width size of the clipping + */ + public void setClippingWidth(final Vector3f _pos, final Vector3f _width) { + setClipping(_pos, _pos.add(_width)); + } + + /** + * @brief set the Color of the current foreground font + * @param[in] _color Color to set on foreground (for next print) + */ + public void setColor(final Color _color) { + this.color = _color; + } + + /** + * @brief set the background color of the font (for selected Text (not the + * global BG)) + * @param[in] _color Color to set on background (for next print) + */ + public void setColorBg(final Color _color) { + this.colorBg = _color; + // TODO this.vectorialDraw.setColor(_color); + } + + /** + * @brief change the cursor color + * @param[in] _color New color for the Selection + */ + public void setCursorColor(final Color _color) { + this.colorCursor = _color; + } + + /** + * @brief set a cursor at a specific position: + * @param[in] _cursorPos id of the cursor position + */ + public void setCursorPos(final int _cursorPos) { + this.selectionStartPos = _cursorPos; + this.cursorPos = _cursorPos; + } + + /** + * @brief set a cursor at a specific position with his associated selection: + * @param[in] _cursorPos id of the cursor position + * @param[in] _selectionStartPos id of the starting of the selection + */ + public void setCursorSelection(final int _cursorPos, final int _selectionStartPos) { + this.selectionStartPos = _selectionStartPos; + this.cursorPos = _cursorPos; + } + + /** + * @brief set the default background color of the font (when reset, set this + * value ...) + * @param[in] _color Color to set on background + */ + public void setDefaultColorBg(final Color _color) { + this.defaultColorBg = _color; + } + + /** + * @brief set the default Foreground color of the font (when reset, set this + * value ...) + * @param[in] _color Color to set on foreground + */ + public void setDefaultColorFg(final Color _color) { + this.defaultColorFg = _color; + } + + /** + * @brief Specify the font property (this reset the internal element of the + * current text (system requirement) + * @param[in] fontName Current name of the selected font + * @param[in] fontSize New font size + */ + public abstract void setFont(final String _fontName, final int _fontSize); + + /** + * @brief enable or disable the bold mode + * @param[in] _status The new status for this display property + */ + public void setFontBold(final boolean _status) { + if (_status == true) { + // enable + if (this.mode == FontMode.Regular) { + setFontMode(FontMode.Bold); + } else if (this.mode == FontMode.Italic) { + setFontMode(FontMode.BoldItalic); + } + } else { + // disable + if (this.mode == FontMode.Bold) { + setFontMode(FontMode.Regular); + } else if (this.mode == FontMode.BoldItalic) { + setFontMode(FontMode.Italic); + } + } + } + + /** + * @brief enable or disable the italic mode + * @param[in] _status The new status for this display property + */ + public void setFontItalic(final boolean _status) { + if (_status == true) { + // enable + if (this.mode == FontMode.Regular) { + setFontMode(FontMode.Italic); + } else if (this.mode == FontMode.Bold) { + setFontMode(FontMode.BoldItalic); + } + } else { + // disable + if (this.mode == FontMode.Italic) { + setFontMode(FontMode.Regular); + } else if (this.mode == FontMode.BoldItalic) { + setFontMode(FontMode.Bold); + } + } + } + + /** + * @brief Specify the font mode for the next @ref print + * @param[in] mode The font mode requested + */ + public abstract void setFontMode(FontMode _mode);; + + /** + * @brief Specify the font name (this reset the internal element of the current + * text (system requirement) + * @param[in] _fontName Current name of the selected font + */ + public abstract void setFontName(final String _fontName); + + /** + * @brief Specify the font size (this reset the internal element of the current + * text (system requirement) + * @param[in] _fontSize New font size + */ + public abstract void setFontSize(final int _fontSize); + + /** + * @brief set the activation of the Kerning for the display (if it existed) + * @param[in] _newMode enable/Diasable the kerning on this font. + */ + public void setKerningMode(final boolean _newMode) { + this.kerning = _newMode; + } + + // ! @previous + public void setPos(final Vector2f _pos) { + setPos(new Vector3f(_pos.x(), _pos.y(), 0)); + } + + /** + * @brief set position for the next text writen + * @param[in] _pos Position of the text (in 3D) + */ + public void setPos(final Vector3f _pos) { + // check min max for display area + if (this.nbCharDisplayed != 0) { + Log.verbose("update size 1 " + this.sizeDisplayStart + " " + this.sizeDisplayStop); + this.sizeDisplayStop = Vector3f.max(this.position, this.sizeDisplayStop); + this.sizeDisplayStart = Vector3f.min(this.position, this.sizeDisplayStart); + } + // update position + this.position = _pos; + this.previousCharcode = 0;// TODO this.vectorialDraw.setPos(this.position); + // update min max of the display area: + if (this.nbCharDisplayed == 0) { + this.sizeDisplayStart = this.position; + this.sizeDisplayStop = this.position.withY(this.sizeDisplayStop.y() + getHeight()); + Log.verbose("update size 0 " + this.sizeDisplayStart + " " + this.sizeDisplayStop); + } else { + Log.verbose("update size 3 " + this.sizeDisplayStart + " " + this.sizeDisplayStop); + this.sizeDisplayStop = Vector3f.max(this.position, this.sizeDisplayStop); + this.sizeDisplayStart = Vector3f.min(this.position, this.sizeDisplayStart); + Log.verbose("update size 4 " + this.sizeDisplayStart + " " + this.sizeDisplayStop); + } + } + + // ! @previous + public void setRelPos(final Vector2f _pos) { + setRelPos(new Vector3f(_pos.x(), _pos.y(), 0)); + } + + /** + * @brief set relative position for the next text written + * @param[in] _pos offset apply of the text (in 3D) + */ + public void setRelPos(final Vector3f _pos) { + this.position = this.position.add(_pos); + this.previousCharcode = 0; + // TODO this.vectorialDraw.setPos(this.position); + } + + /** + * @brief change the selection color + * @param[in] _color New color for the Selection + */ + public void setSelectionColor(final Color _color) { + this.colorSelection = _color; + } + + /** + * @brief This generate the possibility to generate the big text property + * @param[in] _startTextpos The x text start position of the display. + * @param[in] _stopTextPos The x text stop position of the display. + * @param[in] _alignement mode of alignement for the Text. + * @note The text align in center change of line every display done (even if it + * was just a char) + */ + public void setTextAlignement(final float _startTextpos, final float _stopTextPos) { + setTextAlignement(_startTextpos, _stopTextPos, AligneMode.alignDisable); + } + + public void setTextAlignement(final float _startTextpos, final float _stopTextPos, final AligneMode _alignement) { + this.startTextpos = _startTextpos; + this.stopTextPos = _stopTextPos + 1; + this.alignement = _alignement; + if (this.startTextpos >= this.stopTextPos) { + // TODO: understand why this flush ... + Log.verbose("Request allignement with Borne position error : " + _startTextpos + " => " + _stopTextPos); + } + } + + @Override + public void translate(final Vector3f _vect) { + super.translate(_vect); + // TODO this.vectorialDraw.translate(_vect); + } + } \ No newline at end of file diff --git a/src/org/atriasoft/ewol/compositing/tools/TextDecoration.java b/src/org/atriasoft/ewol/compositing/tools/TextDecoration.java index 1b22e23..65d50a2 100644 --- a/src/org/atriasoft/ewol/compositing/tools/TextDecoration.java +++ b/src/org/atriasoft/ewol/compositing/tools/TextDecoration.java @@ -1,10 +1,29 @@ package org.atriasoft.ewol.compositing.tools; +import org.atriasoft.etk.Color; import org.atriasoft.ewol.resource.font.FontMode; -public record TextDecoration( - final Color colorBG, - final Color colorFg, - final FontMode mode) { - +@SuppressWarnings("preview") +public record TextDecoration(Color colorFG, Color colorBG, FontMode mode) { + public TextDecoration(final Color colorFG, final Color colorBG, final FontMode mode) { + this.colorFG = colorFG; + this.colorBG = colorBG; + this.mode = mode; + } + + public TextDecoration() { + this(Color.BLACK, Color.NONE, FontMode.Regular); + } + + public TextDecoration withFG(final Color color) { + return new TextDecoration(color, this.colorBG, this.mode); + } + + public TextDecoration withBG(final Color color) { + return new TextDecoration(this.colorFG, color, this.mode); + } + + public TextDecoration withMode(final FontMode mode) { + return new TextDecoration(this.colorFG, this.colorBG, mode); + } } diff --git a/src/org/atriasoft/ewol/context/EwolContext.java b/src/org/atriasoft/ewol/context/EwolContext.java index 3249f9c..b3ef67c 100644 --- a/src/org/atriasoft/ewol/context/EwolContext.java +++ b/src/org/atriasoft/ewol/context/EwolContext.java @@ -366,7 +366,7 @@ public abstract class EwolContext extends Application { return; } final Vector2f size = getSize(); - this.windowsCurrent.setSize(new Vector2f((int) size.x, (int) size.y)); + this.windowsCurrent.setSize(new Vector2f((int) size.x(), (int) size.y())); this.windowsCurrent.onChangeSize(); } diff --git a/src/org/atriasoft/ewol/context/InputManager.java b/src/org/atriasoft/ewol/context/InputManager.java index 4e2ea31..e57e330 100644 --- a/src/org/atriasoft/ewol/context/InputManager.java +++ b/src/org/atriasoft/ewol/context/InputManager.java @@ -78,13 +78,13 @@ class InputManager { eventMouseSaved2[_idInput].destinationInputId = 0; eventMouseSaved2[_idInput].lastTimeEvent = new Clock(); eventMouseSaved2[_idInput].curentWidgetEvent = null; - eventMouseSaved2[_idInput].origin.setValue(0, 0); - eventMouseSaved2[_idInput].size.setValue(99999999, 99999999); - eventMouseSaved2[_idInput].downStart.setValue(0, 0); + eventMouseSaved2[_idInput].origin = new Vector2f(0, 0); + eventMouseSaved2[_idInput].size = new Vector2f(99999999, 99999999); + eventMouseSaved2[_idInput].downStart = new Vector2f(0, 0); eventMouseSaved2[_idInput].isDown = false; eventMouseSaved2[_idInput].isInside = false; eventMouseSaved2[_idInput].nbClickEvent = 0; - eventMouseSaved2[_idInput].posEvent.setValue(0, 0); + eventMouseSaved2[_idInput].posEvent = new Vector2f(0, 0); } /** @@ -187,8 +187,8 @@ class InputManager { tmpWidget = tmpWindows.getWidgetAtPos(_pos); } if (tmpWidget != eventTable[_pointerID].curentWidgetEvent.get() - || (eventTable[_pointerID].isInside == true && (eventTable[_pointerID].origin.x > _pos.x || eventTable[_pointerID].origin.y > _pos.y - || (eventTable[_pointerID].origin.x + eventTable[_pointerID].size.x) < _pos.x || (eventTable[_pointerID].origin.y + eventTable[_pointerID].size.y) < _pos.y))) { + || (eventTable[_pointerID].isInside == true && (eventTable[_pointerID].origin.x() > _pos.x() || eventTable[_pointerID].origin.y() > _pos.y() + || (eventTable[_pointerID].origin.x() + eventTable[_pointerID].size.x()) < _pos.x() || (eventTable[_pointerID].origin.y() + eventTable[_pointerID].size.y()) < _pos.y()))) { eventTable[_pointerID].isInside = false; //Log.debug("GUI : Input ID=" + _pointerID + " == >" + eventTable[_pointerID].destinationInputId + " [LEAVE] " + _pos); eventTable[_pointerID].posEvent = _pos; @@ -215,15 +215,15 @@ class InputManager { localEventInput(_type, tmpWidget, eventTable[_pointerID].destinationInputId, KeyStatus.move, _pos); } else if (eventTable[_pointerID].isUsed == true) { if (eventTable[_pointerID].isInside == true) { - if (eventTable[_pointerID].origin.x > _pos.x || eventTable[_pointerID].origin.y > _pos.y || (eventTable[_pointerID].origin.x + eventTable[_pointerID].size.x) < _pos.x - || (eventTable[_pointerID].origin.y + eventTable[_pointerID].size.y) < _pos.y) { + if (eventTable[_pointerID].origin.x() > _pos.x() || eventTable[_pointerID].origin.y() > _pos.y() || (eventTable[_pointerID].origin.x() + eventTable[_pointerID].size.x()) < _pos.x() + || (eventTable[_pointerID].origin.y() + eventTable[_pointerID].size.y()) < _pos.y()) { eventTable[_pointerID].isInside = false; //Log.debug("GUI : Input ID=" + _pointerID + " == >" + eventTable[_pointerID].destinationInputId + " [LEAVE] " + _pos); eventTable[_pointerID].posEvent = _pos; localEventInput(_type, eventTable[_pointerID].curentWidgetEvent.get(), eventTable[_pointerID].destinationInputId, KeyStatus.leave, _pos); } - } else if ((eventTable[_pointerID].origin.x <= _pos.x && (eventTable[_pointerID].origin.x + eventTable[_pointerID].size.x) >= _pos.x) - && (eventTable[_pointerID].origin.y <= _pos.y && (eventTable[_pointerID].origin.y + eventTable[_pointerID].size.y) >= _pos.y)) { + } else if ((eventTable[_pointerID].origin.x() <= _pos.x() && (eventTable[_pointerID].origin.x() + eventTable[_pointerID].size.x()) >= _pos.x()) + && (eventTable[_pointerID].origin.y() <= _pos.y() && (eventTable[_pointerID].origin.y() + eventTable[_pointerID].size.y()) >= _pos.y())) { eventTable[_pointerID].isInside = true; //Log.debug("GUI : Input ID=" + _pointerID + " == >" + eventTable[_pointerID].destinationInputId + " [ENTER] " + _pos); eventTable[_pointerID].posEvent = _pos; @@ -291,7 +291,7 @@ class InputManager { // we have an event previously ... check delay between click and offset position if (currentTime.less(eventTable[_pointerID].lastTimeEvent).isGreaterThan(localLimit.sepatateTime)) { cleanElement(eventTable, _pointerID); - } else if (FMath.abs(eventTable[_pointerID].downStart.x - _pos.x) >= localLimit.DpiOffset || FMath.abs(eventTable[_pointerID].downStart.y - _pos.y) >= localLimit.DpiOffset) { + } else if (FMath.abs(eventTable[_pointerID].downStart.x() - _pos.x()) >= localLimit.DpiOffset || FMath.abs(eventTable[_pointerID].downStart.y() - _pos.y()) >= localLimit.DpiOffset) { cleanElement(eventTable, _pointerID); } } @@ -367,7 +367,7 @@ class InputManager { // send up event after the single event to prevent multiple widget getting elements localEventInput(_type, tmpWidget, _pointerID, KeyStatus.up, _pos); // generate event (single) - if (FMath.abs(eventTable[_pointerID].downStart.x - _pos.x) < localLimit.DpiOffset && FMath.abs(eventTable[_pointerID].downStart.y - _pos.y) < localLimit.DpiOffset) { + if (FMath.abs(eventTable[_pointerID].downStart.x() - _pos.x()) < localLimit.DpiOffset && FMath.abs(eventTable[_pointerID].downStart.y() - _pos.y()) < localLimit.DpiOffset) { // Save current position : eventTable[_pointerID].downStart = _pos; // save start time diff --git a/src/org/atriasoft/ewol/object/ObjectManager.java b/src/org/atriasoft/ewol/object/ObjectManager.java index c3e4d43..29d7c75 100644 --- a/src/org/atriasoft/ewol/object/ObjectManager.java +++ b/src/org/atriasoft/ewol/object/ObjectManager.java @@ -38,7 +38,7 @@ public class ObjectManager { Log.todo("set this back ..."); //this.periodicCall.setPeriodic(true); // set the basic time properties : - this.applWakeUpTime = Clock.now(); + this.applWakeUpTime = Time.now(); this.lastPeriodicCallTime = new Clock(this.applWakeUpTime.get()); } diff --git a/src/org/atriasoft/ewol/object/Worker.java b/src/org/atriasoft/ewol/object/Worker.java index 7b58ce7..0e581aa 100644 --- a/src/org/atriasoft/ewol/object/Worker.java +++ b/src/org/atriasoft/ewol/object/Worker.java @@ -1,3 +1,5 @@ +package org.atriasoft.ewol.object; + /** @file * @author Edouard DUPIN * @copyright 2011, Edouard DUPIN, all right reserved diff --git a/src/org/atriasoft/ewol/resource/ResourceTexturedFont.java b/src/org/atriasoft/ewol/resource/ResourceTexturedFont.java index a571a3a..9e1a3fd 100644 --- a/src/org/atriasoft/ewol/resource/ResourceTexturedFont.java +++ b/src/org/atriasoft/ewol/resource/ResourceTexturedFont.java @@ -16,67 +16,90 @@ import org.atriasoft.ewol.internal.Log; import org.atriasoft.ewol.resource.font.FontBase; import org.atriasoft.ewol.resource.font.FontMode; import org.atriasoft.ewol.resource.font.GlyphProperty; +import org.atriasoft.gale.resource.Resource; public class ResourceTexturedFont extends ResourceTexture2 { + public static ResourceTexturedFont create(final String fontName) { + ResourceTexturedFont resource; + Resource resource2; + if (fontName.isEmpty() == false && fontName.contentEquals("---")) { + resource2 = getManager().localKeep(fontName); + } else { + Log.error("Can not create a shader without a filaname"); + return null; + } + if (resource2 != null) { + if (resource2 instanceof ResourceTexturedFont) { + resource2.keep(); + return (ResourceTexturedFont) resource2; + } + Log.critical("Request resource fontName : '" + fontName + "' With the wrong type (dynamic cast error)"); + return null; + } + resource = new ResourceTexturedFont(fontName); + getManager().localAdd(resource); + return resource; + } + /** * @brief Get all the Path contain in the specidy path: * @param[in] _path Generic path to parse ... * @return The list of path found - * @example[start] - * auto out = explodeMultiplePath("DATA:///font?lib=ewol"); - * // out contain: {"DATA:///font", "DATA:///font?lib=ewol"} - * @example[stop] + * @example[start] auto out = explodeMultiplePath("DATA:///font?lib=ewol"); // + * out contain: {"DATA:///font", + * "DATA:///font?lib=ewol"} @example[stop] */ private static List explodeMultiplePath(final Uri _uri) { final List out = new ArrayList<>(); out.add(_uri); return out; } - + private final Uri[] fileName = new Uri[4]; private int size = 10; private final int[] height = new int[4]; // specific element to have the the know if the specify element is known... - // == > otherwise I can just generate italic ... - // == > Bold is a little more complicated (maybe with the bordersize) + // == > otherwise I can just generate italic ... + // == > Bold is a little more complicated (maybe with the bordersize) private final FontBase[] font = new FontBase[4]; - private final FontMode[] modeWraping = new FontMode[4]; //!< This is a wrapping mode to prevent the fact that no font is define for a specific mode + private final FontMode[] modeWraping = new FontMode[4]; // !< This is a wrapping mode to prevent the fact that no + // font is define for a specific mode public GlyphProperty emptyGlyph; public List[] listElement;// = new (List)[4]; - + // for the texture generation : public Vector2i[] lastGlyphPos = new Vector2i[4]; public int[] lastRawHeigh = new int[4]; - + protected ResourceTexturedFont(final String _fontName) { super(_fontName); - + Log.debug("Load font : '" + _fontName + "'"); - + this.font[0] = null; this.font[1] = null; this.font[2] = null; this.font[3] = null; - + this.modeWraping[0] = FontMode.Regular; this.modeWraping[1] = FontMode.Regular; this.modeWraping[2] = FontMode.Regular; this.modeWraping[3] = FontMode.Regular; - - this.lastGlyphPos[0].setValue(1, 1); - this.lastGlyphPos[1].setValue(1, 1); - this.lastGlyphPos[2].setValue(1, 1); - this.lastGlyphPos[3].setValue(1, 1); - + + this.lastGlyphPos[0] = Vector2i.ONE; + this.lastGlyphPos[1] = Vector2i.ONE; + this.lastGlyphPos[2] = Vector2i.ONE; + this.lastGlyphPos[3] = Vector2i.ONE; + this.lastRawHeigh[0] = 0; this.lastRawHeigh[1] = 0; this.lastRawHeigh[2] = 0; this.lastRawHeigh[3] = 0; - + int tmpSize = 0; // extarct name and size : final String[] tmpList = _fontName.split(":"); - + if (tmpList.length == 1) { this.size = 1; Log.critical("Can not parse the font name: '" + _fontName + "' ??? ':' "); @@ -85,23 +108,22 @@ public class ResourceTexturedFont extends ResourceTexture2 { // zsdefsdf tmpSize = Integer.valueOf(tmpList[1]); } - + final String localName = tmpList[0]; if (tmpSize > 400) { Log.error("Font size too big ==> limit at 400 when exceed ==> error: " + tmpSize + "==>30"); tmpSize = 30; } this.size = tmpSize; - + final List folderList = new ArrayList<>(); - ; if (Ewol.getContext().getFontDefault().getUseExternal() == true) { /* - #if defined(__TARGET_OS__Android) - folderList.pushBack(etk::Path("/system/fonts"));#elif defined(__TARGET_OS__Linux) - folderList.pushBack(etk::Path("/usr/share/fonts")); - #endif - */ + * #if defined(__TARGET_OS__Android) + * folderList.pushBack(etk::Path("/system/fonts"));#elif + * defined(__TARGET_OS__Linux) + * folderList.pushBack(etk::Path("/usr/share/fonts")); #endif + */ } final Uri applicationBaseFont = Ewol.getContext().getFontDefault().getFolder(); for (final Uri it : explodeMultiplePath(applicationBaseFont)) { @@ -109,38 +131,51 @@ public class ResourceTexturedFont extends ResourceTexture2 { } for (int folderID = 0; folderID < folderList.size(); folderID++) { final List output = Uri.listRecursive(folderList.get(folderID)); - + final String[] split = localName.split(";"); Log.debug("try to find font named : " + split + " in: " + output); - //Log.critical("parse string : " + split); + // Log.critical("parse string : " + split); boolean hasFindAFont = false; for (int jjj = 0; jjj < split.length; jjj++) { Log.debug(" try with : '" + split[jjj] + "'"); for (int iii = 0; iii < output.size(); iii++) { final String nameFolder = output.get(iii).getPath(); - //Log.debug(" file : " + output.get(iii)); - if (nameFolder.endsWith(split[jjj] + "-" + "bold" + ".ttf") == true || nameFolder.endsWith(split[jjj] + "-" + "b" + ".ttf") == true - || nameFolder.endsWith(split[jjj] + "-" + "bd" + ".ttf") == true || nameFolder.endsWith(split[jjj] + "bold" + ".ttf") == true - || nameFolder.endsWith(split[jjj] + "bd" + ".ttf") == true || nameFolder.endsWith(split[jjj] + "b" + ".ttf") == true) { + // Log.debug(" file : " + output.get(iii)); + if (nameFolder.endsWith(split[jjj] + "-" + "bold" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "-" + "b" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "-" + "bd" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "bold" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "bd" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "b" + ".ttf") == true) { Log.debug(" find Font [Bold] : " + output.get(iii)); this.fileName[FontMode.Bold.getValue()] = output.get(iii); hasFindAFont = true; - } else if (nameFolder.endsWith(split[jjj] + "-" + "oblique" + ".ttf") == true || nameFolder.endsWith(split[jjj] + "-" + "italic" + ".ttf") == true - || nameFolder.endsWith(split[jjj] + "-" + "Light" + ".ttf") == true || nameFolder.endsWith(split[jjj] + "-" + "i" + ".ttf") == true - || nameFolder.endsWith(split[jjj] + "oblique" + ".ttf") == true || nameFolder.endsWith(split[jjj] + "italic" + ".ttf") == true - || nameFolder.endsWith(split[jjj] + "light" + ".ttf") == true || nameFolder.endsWith(split[jjj] + "i" + ".ttf") == true) { + } else if (nameFolder.endsWith(split[jjj] + "-" + "oblique" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "-" + "italic" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "-" + "Light" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "-" + "i" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "oblique" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "italic" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "light" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "i" + ".ttf") == true) { Log.debug(" find Font [Italic] : " + output.get(iii)); this.fileName[FontMode.Italic.getValue()] = output.get(iii); hasFindAFont = true; - } else if (nameFolder.endsWith(split[jjj] + "-" + "bolditalic" + ".ttf") == true || nameFolder.endsWith(split[jjj] + "-" + "boldoblique" + ".ttf") == true - || nameFolder.endsWith(split[jjj] + "-" + "bi" + ".ttf") == true || nameFolder.endsWith(split[jjj] + "-" + "z" + ".ttf") == true - || nameFolder.endsWith(split[jjj] + "bolditalic" + ".ttf") == true || nameFolder.endsWith(split[jjj] + "boldoblique" + ".ttf") == true - || nameFolder.endsWith(split[jjj] + "bi" + ".ttf") == true || nameFolder.endsWith(split[jjj] + "z" + ".ttf") == true) { + } else if (nameFolder.endsWith(split[jjj] + "-" + "bolditalic" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "-" + "boldoblique" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "-" + "bi" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "-" + "z" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "bolditalic" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "boldoblique" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "bi" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "z" + ".ttf") == true) { Log.debug(" find Font [Bold-Italic] : " + output.get(iii)); this.fileName[FontMode.BoldItalic.getValue()] = output.get(iii); hasFindAFont = true; - } else if (nameFolder.endsWith(split[jjj] + "-" + "regular" + ".ttf") == true || nameFolder.endsWith(split[jjj] + "-" + "r" + ".ttf") == true - || nameFolder.endsWith(split[jjj] + "regular" + ".ttf") == true || nameFolder.endsWith(split[jjj] + "r" + ".ttf") == true + } else if (nameFolder.endsWith(split[jjj] + "-" + "regular" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "-" + "r" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "regular" + ".ttf") == true + || nameFolder.endsWith(split[jjj] + "r" + ".ttf") == true || nameFolder.endsWith(split[jjj] + ".ttf") == true) { Log.debug(" find Font [Regular] : " + output.get(iii)); this.fileName[FontMode.Regular.getValue()] = output.get(iii); @@ -177,17 +212,20 @@ public class ResourceTexturedFont extends ResourceTexture2 { this.modeWraping[iii] = refMode; } } - + for (int iiiFontId = 0; iiiFontId < 4; iiiFontId++) { if (this.fileName[iiiFontId] == null) { - Log.debug("can not load FONT [" + iiiFontId + "] name : \"" + this.fileName[iiiFontId] + "\" == > size=" + this.size); + Log.debug("can not load FONT [" + iiiFontId + "] name : \"" + this.fileName[iiiFontId] + + "\" == > size=" + this.size); this.font[iiiFontId] = null; continue; } - Log.debug("Load FONT [" + iiiFontId + "] name : \"" + this.fileName[iiiFontId] + "\" == > size=" + this.size); + Log.debug("Load FONT [" + iiiFontId + "] name : \"" + this.fileName[iiiFontId] + "\" == > size=" + + this.size); this.font[iiiFontId] = ResourceFontFreeType.create(this.fileName[iiiFontId]); if (this.font[iiiFontId] == null) { - Log.debug("error in loading FONT [" + iiiFontId + "] name : \"" + this.fileName[iiiFontId] + "\" == > size=" + this.size); + Log.debug("error in loading FONT [" + iiiFontId + "] name : \"" + this.fileName[iiiFontId] + + "\" == > size=" + this.size); } } for (int iiiFontId = 0; iiiFontId < 4; iiiFontId++) { @@ -197,7 +235,8 @@ public class ResourceTexturedFont extends ResourceTexture2 { continue; } this.height[iiiFontId] = this.font[iiiFontId].getHeight(this.size); - // TODO : basic font use 512 is better ... == > maybe estimate it with the dpi ??? + // TODO : basic font use 512 is better ... == > maybe estimate it with the dpi + // ??? setImageSize(new Vector2i(256, 32)); // now we can acces directly on the image this.data.clear(); @@ -216,7 +255,7 @@ public class ResourceTexturedFont extends ResourceTexture2 { Log.debug(" " + FontMode.Bold + " == >" + getWrappingMode(FontMode.Bold)); Log.debug(" " + FontMode.BoldItalic + " == >" + getWrappingMode(FontMode.BoldItalic)); } - + /** * @brief add a glyph in a texture font. * @param[in] _val Char value to add. @@ -232,79 +271,85 @@ public class ResourceTexturedFont extends ResourceTexture2 { // add the curent "char" final GlyphProperty tmpchar = new GlyphProperty(); tmpchar.UVal = _val; - + if (this.font[iii].getGlyphProperty(this.size, tmpchar) == true) { - //Log.debug("load char : '" + _val + "'=" + _val.get()); + // Log.debug("load char : '" + _val + "'=" + _val.get()); hasChange = true; // change line if needed ... - if (this.lastGlyphPos[iii].x + tmpchar.sizeTexture.x + 3 > this.data.getSize().x) { - this.lastGlyphPos[iii].setX(1); - this.lastGlyphPos[iii].add(new Vector2i(0, this.lastRawHeigh[iii])); + if (this.lastGlyphPos[iii].x() + tmpchar.sizeTexture.x() + 3 > this.data.getSize().x()) { + this.lastGlyphPos[iii] = new Vector2i(1, this.lastRawHeigh[iii]); this.lastRawHeigh[iii] = 0; } - while (this.lastGlyphPos[iii].y + tmpchar.sizeTexture.y + 3 > this.data.getSize().y) { - final Vector2i size = this.data.getSize(); - size.setY(size.y * 2); - this.data.resize(size.x, size.y); - // note : need to rework all the lyer due to the fact that the texture is used by the faur type... + while (this.lastGlyphPos[iii].y() + tmpchar.sizeTexture.y() + 3 > this.data.getSize().y()) { + this.data.resize(this.data.getSize().x(), this.data.getSize().y() * 2); + // note : need to rework all the lyer due to the fact that the texture is used + // by the faur type... for (int kkk = 0; kkk < 4; kkk++) { // change the coordonate on the element in the texture for (int jjj = 0; jjj < this.listElement[kkk].size(); ++jjj) { - this.listElement[kkk].get(jjj).texturePosStart.multiply(new Vector2f(1.0f, 0.5f)); - this.listElement[kkk].get(jjj).texturePosSize.multiply(new Vector2f(1.0f, 0.5f)); + this.listElement[kkk] + .get(jjj).texturePosStart = this.listElement[kkk].get(jjj).texturePosStart + .multiply(new Vector2f(1.0f, 0.5f)); + this.listElement[kkk] + .get(jjj).texturePosSize = this.listElement[kkk].get(jjj).texturePosSize + .multiply(new Vector2f(1.0f, 0.5f)); } } } // draw the glyph this.font[iii].drawGlyph(this.data, this.size, this.lastGlyphPos[iii], tmpchar, iii); // set video position - tmpchar.texturePosStart.setValue((float) this.lastGlyphPos[iii].x / (float) this.data.getSize().x, (float) this.lastGlyphPos[iii].y / (float) this.data.getSize().y); - tmpchar.texturePosSize.setValue((float) tmpchar.sizeTexture.x / this.data.getSize().x, (float) tmpchar.sizeTexture.y / this.data.getSize().y); - - // update the maximum of the line hight : - if (this.lastRawHeigh[iii] < tmpchar.sizeTexture.y) { + tmpchar.texturePosStart = new Vector2f( + (float) this.lastGlyphPos[iii].x() / (float) this.data.getSize().x(), + (float) this.lastGlyphPos[iii].y() / (float) this.data.getSize().y()); + tmpchar.texturePosSize = new Vector2f((float) tmpchar.sizeTexture.x() / this.data.getSize().x(), + (float) tmpchar.sizeTexture.y() / this.data.getSize().y()); + + // update the maximum of the line hight : + if (this.lastRawHeigh[iii] < tmpchar.sizeTexture.y()) { // note : +1 is for the overlapping of the glyph (Part 2) - this.lastRawHeigh[iii] = tmpchar.sizeTexture.y + 1; + this.lastRawHeigh[iii] = tmpchar.sizeTexture.y() + 1; } // note : +1 is for the overlapping of the glyph (Part 3) - // update the Bitmap position drawing : - this.lastGlyphPos[iii].add(new Vector2i(tmpchar.sizeTexture.x + 1, 0)); + // update the Bitmap position drawing : + this.lastGlyphPos[iii] = this.lastGlyphPos[iii].add(new Vector2i(tmpchar.sizeTexture.x() + 1, 0)); } else { Log.warning("Did not find char : '" + _val + "'=" + _val); tmpchar.setNotExist(); } this.listElement[iii].add(tmpchar); - //this.font[iii].display; + // this.font[iii].display; // generate the kerning for all the characters : if (tmpchar.exist() == true) { // TODO : set the kerning back ... - //this.font[iii].generateKerning(this.size, this.listElement[iii]); + // this.font[iii].generateKerning(this.size, this.listElement[iii]); } } if (hasChange == true) { flush(); Ewol.getContext().forceRedrawAll(); - //egami::store(this.data, "fileFont.bmp"); // ==> for debug test only ... + // egami::store(this.data, "fileFont.bmp"); // ==> for debug test only ... } return hasChange; } - + /** * @brief get the font height (user friendly) * @return Dimention of the font the user requested */ - private int getFontSize() { + public int getFontSize() { return this.size; } - + /** * @brief get the pointer on the coresponding glyph * @param[in] _charcode The unicodeValue * @param[in] _displayMode Mode to display the currrent font - * @return The pointer on the glyph == > never null + * @return The pointer on the glyph == > never null */ - private synchronized GlyphProperty getGlyph(final Character _charcode, final FontMode _displayMode) { - //Log.debug("Get glyph property for mode: " + _displayMode + " == > wrapping index : " + this.modeWraping[_displayMode]); + public synchronized GlyphProperty getGlyph(final Character _charcode, final FontMode _displayMode) { + // Log.debug("Get glyph property for mode: " + _displayMode + " == > wrapping + // index : " + this.modeWraping[_displayMode]); final int index = getIndex(_charcode, _displayMode); if (index < 0 || index >= this.listElement[_displayMode.getValue()].size()) { Log.error(" Try to get glyph index inexistant ... == > return the index 0 ... id=" + index); @@ -313,27 +358,28 @@ public class ResourceTexturedFont extends ResourceTexture2 { } return this.emptyGlyph; } - //Log.error(" index=" + index); - //Log.error(" this.UVal=" + this.listElement[_displayMode][index].UVal); - //Log.error(" this.glyphIndex=" + this.listElement[_displayMode][index].glyphIndex); - //Log.error(" this.advance=" + this.listElement[_displayMode][index].advance); - //Log.error(" this.bearing=" + this.listElement[_displayMode][index].bearing); + // Log.error(" index=" + index); + // Log.error(" this.UVal=" + this.listElement[_displayMode][index].UVal); + // Log.error(" this.glyphIndex=" + + // this.listElement[_displayMode][index].glyphIndex); + // Log.error(" this.advance=" + this.listElement[_displayMode][index].advance); + // Log.error(" this.bearing=" + this.listElement[_displayMode][index].bearing); return this.listElement[_displayMode.getValue()].get(index); }; - + /** * @brief get the display height of this font * @param[in] _displayMode Mode to display the currrent font * @return Dimention of the font need between 2 lines */ - private int getHeight() { + public int getHeight() { return this.height[FontMode.Regular.getValue()]; } - - private int getHeight(final FontMode _displayMode) { + + public int getHeight(final FontMode _displayMode) { return this.height[_displayMode.getValue()]; } - + /** * @brief get the ID of a unicode charcode * @param[in] _charcode The unicodeValue @@ -347,11 +393,12 @@ public class ResourceTexturedFont extends ResourceTexture2 { return _charcode - 0x1F; } else { for (int iii = 0x80 - 0x20; iii < this.listElement[_displayMode.getValue()].size(); iii++) { - //Log.debug("search : '" + charcode + "' =?= '" + (this.listElement[displayMode])[iii].UVal + "'"); + // Log.debug("search : '" + charcode + "' =?= '" + + // (this.listElement[displayMode])[iii].UVal + "'"); if (_charcode == this.listElement[_displayMode.getValue()].get(iii).UVal) { - //Log.debug("search : '" + charcode + "'"); + // Log.debug("search : '" + charcode + "'"); if (this.listElement[_displayMode.getValue()].get(iii).exist()) { - //Log.debug("return " + iii); + // Log.debug("return " + iii); return iii; } else { return 0; @@ -360,19 +407,21 @@ public class ResourceTexturedFont extends ResourceTexture2 { } } if (addGlyph(_charcode) == true) { - // TODO : This does not work due to the fact that the update of open GL is not done in the context main cycle !!! + // TODO : This does not work due to the fact that the update of open GL is not + // done in the context main cycle !!! Ewol.getContext().forceRedrawAll(); } return 0; }; - + /** - * @brief The wrapping mode is used to prevent the non existance of a specific mode. - * For exemple when a blod mode does not exist, this resend a regular mode. + * @brief The wrapping mode is used to prevent the non existance of a specific + * mode. For exemple when a blod mode does not exist, this resend a + * regular mode. * @param[in] _source The requested mode. * @return the best mode we have in stock. */ - private FontMode getWrappingMode(final FontMode _source) { + public FontMode getWrappingMode(final FontMode _source) { return this.modeWraping[_source.getValue()]; } }