//----------------------------------------------------------------------- // //ORIGINAL LINE: MultiShape _booleanOperation(const Shape& STLAllocator<U, AllocPolicy>, BooleanOperationType opType) const private MultiShape _booleanOperation(Shape other, BooleanOperationType opType) { if (!mClosed || mPoints.size() < 2) OGRE_EXCEPT("Ogre::Exception::ERR_INVALID_STATE", "Current shapes must be closed and has to contain at least 2 points!", "Procedural::Shape::_booleanOperation(const Procedural::Shape&, Procedural::BooleanOperationType)"); if (!other.mClosed || other.mPoints.size() < 2) OGRE_EXCEPT("Ogre::Exception::ERR_INVALIDPARAMS", "Other shapes must be closed and has to contain at least 2 points!", "Procedural::Shape::_booleanOperation(const Procedural::Shape&, Procedural::BooleanOperationType)"); ; // Compute the intersection between the 2 shapes std_vector<IntersectionInShape> intersections = new std_vector<IntersectionInShape>(); _findAllIntersections(other, ref intersections); // Build the resulting shape if (intersections.empty()) { if (isPointInside(other.getPoint(0))) { // Shape B is completely inside shape A if (opType == BooleanOperationType.BOT_UNION) { MultiShape ms = new MultiShape(); ms.addShape(this); return ms; } else if (opType == BooleanOperationType.BOT_INTERSECTION) { MultiShape ms = new MultiShape(); ms.addShape(other); return ms; } else if (opType == BooleanOperationType.BOT_DIFFERENCE) { MultiShape ms = new MultiShape(); ms.addShape(this); ms.addShape(other); ms.getShape(1).switchSide(); return ms; } } else if (other.isPointInside(getPoint(0))) { // Shape A is completely inside shape B if (opType == BooleanOperationType.BOT_UNION) { MultiShape ms = new MultiShape(); ms.addShape(other); return ms; } else if (opType == BooleanOperationType.BOT_INTERSECTION) { MultiShape ms = new MultiShape(); ms.addShape(this); return ms; } else if (opType == BooleanOperationType.BOT_DIFFERENCE) { MultiShape ms = new MultiShape(); ms.addShape(this); ms.addShape(other); ms.getShape(0).switchSide(); return ms; } } else { if (opType == BooleanOperationType.BOT_UNION) { MultiShape ms = new MultiShape(); ms.addShape(this); ms.addShape(other); return ms; } else if (opType == BooleanOperationType.BOT_INTERSECTION) return new MultiShape(); //empty result else if (opType == BooleanOperationType.BOT_DIFFERENCE) return new MultiShape(); //empty result } } MultiShape outputMultiShape = new MultiShape(); Shape[] inputShapes = new Shape[2]; inputShapes[0] = this; inputShapes[1] = other; while (!intersections.empty()) { Shape outputShape = new Shape(); byte shapeSelector = 0; // 0 : first shape, 1 : second shape Vector2 currentPosition = intersections[0].position;//intersections.GetEnumerator().position; IntersectionInShape firstIntersection = intersections[0];//*intersections.GetEnumerator(); uint currentSegment = firstIntersection.index[shapeSelector]; //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent to the STL vector 'erase' method in C#: //intersections.erase(intersections.GetEnumerator());//ÒƳý intersections.erase(firstIntersection, true); outputShape.addPoint(currentPosition); sbyte isIncreasing = 0; // +1 if increasing, -1 if decreasing, 0 if undefined if (!_findWhereToGo(inputShapes, opType, firstIntersection, ref shapeSelector, ref isIncreasing, ref currentSegment)) { // That intersection is located on a place where the resulting shape won't go => discard continue; } while (true) { // find the closest intersection on the same segment, in the correct direction //List<IntersectionInShape>.Enumerator found_next_intersection = intersections.end(); IntersectionInShape found_next_intersection = intersections[intersections.Count - 1]; int found_next_intersection_pos = -1; float distanceToNextIntersection = float.MaxValue;// std.numeric_limits<Real>.max(); uint nextPoint = currentSegment + (uint)(isIncreasing == 1 ? 1 : 0); bool nextPointIsOnIntersection = false; //for (List<IntersectionInShape>.Enumerator it = intersections.GetEnumerator(); it.MoveNext(); ++it) for (int i = 0; i < intersections.Count; i++) { IntersectionInShape it = intersections[i]; if (currentSegment == it.index[shapeSelector]) { if (((it.position - currentPosition).DotProduct(it.position - inputShapes[shapeSelector].getPoint((int)nextPoint)) < 0f) || (it.onVertex[shapeSelector] && nextPoint == it.index[shapeSelector])) { // found an intersection between the current one and the next segment point float d = (it.position - currentPosition).Length; if (d < distanceToNextIntersection) { // check if we have the nearest intersection found_next_intersection = it; found_next_intersection_pos = i; distanceToNextIntersection = d; } } } if (nextPoint == it.index[shapeSelector] && it.onVertex[shapeSelector]) nextPointIsOnIntersection = true; } // stop condition if (currentSegment == firstIntersection.index[shapeSelector]) { // we found ourselves on the same segment as the first intersection and no other if ((firstIntersection.position - currentPosition).DotProduct(firstIntersection.position - inputShapes[shapeSelector].getPoint((int)nextPoint)) < 0f) { float d = (firstIntersection.position - currentPosition).Length; if (d > 0.0f && d < distanceToNextIntersection) { outputShape.close(); break; } } } // We actually found the next intersection => change direction and add current intersection to the list //if (found_next_intersection.MoveNext()) //if (intersections.Count > 1) { if (found_next_intersection_pos != -1) { //IntersectionInShape currentIntersection = found_next_intersection.Current; IntersectionInShape currentIntersection = found_next_intersection; intersections.erase(found_next_intersection, true); //IntersectionInShape currentIntersection = intersections[intersections.Count - 1]; outputShape.addPoint(currentIntersection.position); bool result = _findWhereToGo(inputShapes, opType, currentIntersection, ref shapeSelector, ref isIncreasing, ref currentSegment); if (result == null) { OGRE_EXCEPT("Ogre::Exception::ERR_INTERNAL_ERROR", "We should not be here!", "Procedural::Shape::_booleanOperation(const Procedural::Shape&, Procedural::BooleanOperationType)"); ; } } else { // no intersection found for the moment => just continue on the current segment if (!nextPointIsOnIntersection) { if (isIncreasing == 1) currentPosition = inputShapes[shapeSelector].getPoint((int)currentSegment + 1); else currentPosition = inputShapes[shapeSelector].getPoint((int)currentSegment); outputShape.addPoint(currentPosition); } currentSegment = (uint)Utils.modulo((int)currentSegment + isIncreasing, inputShapes[shapeSelector].getSegCount()); } } outputMultiShape.addShape(outputShape); } return outputMultiShape; }
/// Creates a shape with the keys of this shape and extra keys coming from a track /// @param track the track to merge keys with /// @return a new Shape coming from the merge between original shape and the track //----------------------------------------------------------------------- // //ORIGINAL LINE: Shape mergeKeysWithTrack(const Track& track) const public Shape mergeKeysWithTrack(Track track) { if (!track.isInsertPoint() || track.getAddressingMode() == Track.AddressingMode.AM_POINT) return this; float totalLength = getTotalLength(); float lineicPos = 0; float shapeLineicPos = 0; Shape outputShape = new Shape(); if (mClosed) outputShape.close(); outputShape.addPoint(getPoint(0)); for (int i = 1; i < mPoints.Count; ) { float nextLineicPos = shapeLineicPos + (mPoints[i] - mPoints[i - 1]).Length; //std.map<Real,Real>.Enumerator it = track._getKeyValueAfter(lineicPos, lineicPos/totalLength, i-1); std_pair<float, float> it = track._getKeyValueAfter(lineicPos, lineicPos / totalLength, ((uint)i - 1)); float nextTrackPos = it.first; if (track.getAddressingMode() == Track.AddressingMode.AM_RELATIVE_LINEIC) nextTrackPos *= totalLength; // Adds the closest point to the curve, being either from the shape or the track if (nextLineicPos <= nextTrackPos || lineicPos >= nextTrackPos) { outputShape.addPoint(mPoints[i]); i++; lineicPos = nextLineicPos; shapeLineicPos = nextLineicPos; } else { outputShape.addPoint(getPosition((uint)i - 1, (nextTrackPos - shapeLineicPos) / (nextLineicPos - shapeLineicPos))); lineicPos = nextTrackPos; } } return outputShape; }
// * // * Applies a "thickness" to a shape, ie a bit like the extruder, but in 2D // * <table border="0" width="100%"><tr><td>\image html shape_thick1.png "Start shape (before thicken)"</td><td>\image html shape_thick2.png "Result (after thicken)"</td></tr></table> // //----------------------------------------------------------------------- public MultiShape thicken(float amount) { if (!mClosed) { Shape s = new Shape(); s.setOutSide(mOutSide); for (int i = 0; i < mPoints.Count; i++) s.addPoint(mPoints[i] + amount * getAvgNormal((uint)i)); for (int i = mPoints.Count - 1; i >= 0; i--) s.addPoint(mPoints[i] - amount * getAvgNormal((uint)i)); s.close(); return new MultiShape().addShape(s); } else { MultiShape ms = new MultiShape(); Shape s1 = new Shape(); for (int i = 0; i < mPoints.Count; i++) s1.addPoint(mPoints[i] + amount * getAvgNormal((uint)i)); s1.close(); s1.setOutSide(mOutSide); ms.addShape(s1); Shape s2 = new Shape(); for (int i = 0; i < mPoints.Count; i++) s2.addPoint(mPoints[i] - amount * getAvgNormal((uint)i)); s2.close(); s2.setOutSide(mOutSide == Side.SIDE_LEFT ? Side.SIDE_RIGHT : Side.SIDE_LEFT); ms.addShape(s2); return ms; } }
// * // * Computes the union between this shape and another one. // * Both shapes must be closed. // * <table border="0" width="100%"><tr><td>\image html shape_booleansetup.png "Start shapes"</td><td>\image html shape_booleanunion.png "Union of the two shapes"</td></tr></table> // * @param other The shape against which the union is computed // * @return The union of two shapes, as a new shape // * @exception Ogre::InvalidStateException Current shapes must be closed and has to contain at least 2 points! // * @exception Ogre::InvalidParametersException Other shapes must be closed and has to contain at least 2 points! // //----------------------------------------------------------------------- // //ORIGINAL LINE: MultiShape booleanUnion(const Shape& STLAllocator<U, AllocPolicy>) const public MultiShape booleanUnion(Shape other) { return _booleanOperation(other, BooleanOperationType.BOT_UNION); }
// * // * Computes the difference between this shape and another one. // * Both shapes must be closed. // * <table border="0" width="100%"><tr><td>\image html shape_booleansetup.png "Start shapes"</td><td>\image html shape_booleandifference.png "Difference of the two shapes"</td></tr></table> // * @param other The shape against which the diffenrence is computed // * @return The difference of two shapes, as a new shape // * @exception Ogre::InvalidStateException Current shapes must be closed and has to contain at least 2 points! // * @exception Ogre::InvalidParametersException Other shapes must be closed and has to contain at least 2 points! // //----------------------------------------------------------------------- // //ORIGINAL LINE: MultiShape booleanDifference(const Shape& STLAllocator<U, AllocPolicy>) const public MultiShape booleanDifference(Shape other) { return _booleanOperation(other, BooleanOperationType.BOT_DIFFERENCE); }
/// Extracts a part of the shape as a new shape /// @param first first index to be in the new shape /// @param last last index to be in the new shape public Shape extractSubShape(uint first, uint last) { Shape s = new Shape(); for (int i = (int)first; i <= last; i++) s.addPoint(mPoints[i]); s.setOutSide(mOutSide); if (mClosed) s.close(); return s; }
// * // * Computes the intersection between this shape and another one. // * Both shapes must be closed. // * <table border="0" width="100%"><tr><td>\image html shape_booleansetup.png "Start shapes"</td><td>\image html shape_booleanintersection.png "Intersection of the two shapes"</td></tr></table> // * @param other The shape against which the intersection is computed // * @return The intersection of two shapes, as a new shape // * @exception Ogre::InvalidStateException Current shapes must be closed and has to contain at least 2 points! // * @exception Ogre::InvalidParametersException Other shapes must be closed and has to contain at least 2 points! // //----------------------------------------------------------------------- //----------------------------------------------------------------------- // //ORIGINAL LINE: MultiShape booleanIntersect(const Shape& STLAllocator<U, AllocPolicy>) const public MultiShape booleanIntersect(Shape other) { return _booleanOperation(other, BooleanOperationType.BOT_INTERSECTION); }
/// Appends another shape at the end of this one public Shape appendShape(Shape other) { // //mPoints.insert(mPoints.end(), STLAllocator<U, AllocPolicy>.mPoints.GetEnumerator(), STLAllocator<U, AllocPolicy>.mPoints.end()); mPoints.AddRange(other.mPoints.ToArray()); return this; }
/// Appends another shape at the end of this one, relative to the last point of this shape public Shape appendShapeRel(Shape other) { return addPointRel(other.mPoints); //if (mPoints.Count == 0) // appendShape(other); //else { // Vector2 refVector = mPoints[mPoints.Count - 1];// *(mPoints.end()-1); // List<Vector2> pointList = other.mPoints;//new List<Vector2>(STLAllocator<U, AllocPolicy>.mPoints.GetEnumerator(), STLAllocator<U, AllocPolicy>.mPoints.end()); // // for (List<Vector2>.Enumerator it = pointList.GetEnumerator(); it.MoveNext(); ++it) // // it.Current +=refVector; // //// // // mPoints.insert(mPoints.end(), pointList.GetEnumerator(), pointList.end()); // foreach (var it in pointList) { // addPoint(it + refVector); // } //} //return this; }
//----------------------------------------------------------------------- // //ORIGINAL LINE: void _findAllIntersections(const Shape& STLAllocator<U, AllocPolicy>, List<IntersectionInShape>& intersections) const private void _findAllIntersections(Shape other, ref std_vector<IntersectionInShape> intersections) { for (ushort i = 0; i < getSegCount(); i++) { Segment2D seg1 = new Segment2D(getPoint(i), getPoint(i + 1)); for (ushort j = 0; j < other.getSegCount(); j++) { Segment2D seg2 = new Segment2D(other.getPoint(j), other.getPoint(j + 1)); Vector2 intersect = new Vector2(); if (seg1.findIntersect(seg2, ref intersect)) { IntersectionInShape inter = new IntersectionInShape(i, j, intersect); // check if intersection is "borderline" : too near to a vertex if ((seg1.mA - intersect).SquaredLength < 1e-8) { inter.onVertex[0] = true; } if ((seg1.mB - intersect).SquaredLength < 1e-8) { inter.onVertex[0] = true; inter.index[0]++; } if ((seg2.mA - intersect).SquaredLength < 1e-8) { inter.onVertex[1] = true; } if ((seg2.mB - intersect).SquaredLength < 1e-8) { inter.onVertex[1] = true; inter.index[1]++; } intersections.push_back(inter); } } } }
//----------------------------------------------------------------------- // //ORIGINAL LINE: bool _findWhereToGo(const Shape* inputShapes[], BooleanOperationType opType, IntersectionInShape intersection, byte& shapeSelector, sbyte& isIncreasing, uint& currentSegment) const private bool _findWhereToGo(Shape[] inputShapes, BooleanOperationType opType, IntersectionInShape intersection, ref byte shapeSelector, ref sbyte isIncreasing, ref uint currentSegment) { if (intersection.onVertex[0] || intersection.onVertex[1]) { // determine 4 directions with normal info // if 2 normals "face each other" then you have the couple of outside directions Vector2[] directions = new Vector2[4]; //string sides = new string(new char[4]); byte[] sides = new byte[4]; byte incomingDirection; // fill-in the incoming arrays if (isIncreasing == 0) { incomingDirection = 255; } else { incomingDirection = (byte)(shapeSelector + (isIncreasing == 1 ? 2 : 0)); } for (byte i = 0; i < 2; i++) if (intersection.onVertex[i]) { directions[i] = inputShapes[i].getDirectionBefore(intersection.index[i]); directions[2 + i] = -inputShapes[i].getDirectionAfter(intersection.index[i]); } else { directions[2 + i] = -inputShapes[i].getDirectionAfter(intersection.index[i]); directions[i] = -directions[2 + i]; } for (byte i = 0; i < 4; i++) { sides[i] = (byte)((i / 2 == 0 ? -1 : 1) * (inputShapes[i % 2].mOutSide == Side.SIDE_RIGHT ? -1 : 1)); } bool[] isOutside = new bool[4]; //std.pair<Radian, byte>[] sortedDirections = new std.pair[4]; KeyValuePair<Radian, byte>[] sortedDirections = new KeyValuePair<Radian, byte>[4]; // sort by angle for (byte i = 0; i < 4; i++) { if (i == 0) { //sortedDirections[i].first = 0; sortedDirections[i] = new KeyValuePair<Radian, byte>(0, i); } else { Radian first = sides[0] * Utils.angleTo(directions[0], directions[i]); sortedDirections[i] = new KeyValuePair<Radian, byte>(first, i); } //sortedDirections[i].second=i; } //std.sort(sortedDirections, sortedDirections+4, GlobalMembersProceduralShape._sortAngles); //ToDo:sortedDirectionsÅÅÐò List<KeyValuePair<Radian, byte>> sort_sortedDirections = new List<KeyValuePair<Radian, byte>>(); sort_sortedDirections.AddRange(sortedDirections); sort_sortedDirections.Sort((X, Y) => { return _sortAngles(X, Y) ? -1 : 1; }); sortedDirections = sort_sortedDirections.ToArray(); //Array.Sort(sortedDirections); //find which segments are outside if (sides[0] != sides[sortedDirections[1].Value]) { isOutside[0] = isOutside[sortedDirections[1].Value] = true; isOutside[sortedDirections[2].Value] = isOutside[sortedDirections[3].Value] = false; } else { isOutside[sortedDirections[1].Value] = isOutside[sortedDirections[2].Value] = true; isOutside[sortedDirections[3].Value] = isOutside[sortedDirections[0].Value] = false; } //find first eligible segment that is not the current segment for (ushort i = 0; i < 4; i++) if ((isOutside[i] == _isLookingForOutside(opType, (sbyte)(i % 2))) && (i != incomingDirection)) { shapeSelector = (byte)(i % 2); isIncreasing = (sbyte)(i / 2 == 0 ? 1 : -1); currentSegment = intersection.index[shapeSelector]; return true; } // if we reach here, it means that no segment is eligible! (it should only happen with difference opereation return false; } else { // determine which way to go int nextShapeSelector = (shapeSelector + 1) % 2; float d = inputShapes[nextShapeSelector].getDirectionAfter(intersection.index[nextShapeSelector]).DotProduct(inputShapes[shapeSelector].getNormalAfter(currentSegment)); isIncreasing = _isIncreasing(d, opType, (sbyte)nextShapeSelector); shapeSelector = (byte)nextShapeSelector; currentSegment = intersection.index[shapeSelector]; return true; } }
/// Converts the path to a shape, with Y=0 //----------------------------------------------------------------------- // //ORIGINAL LINE: Shape convertToShape() const public Shape convertToShape() { Shape s = new Shape(); //for (List<Vector3>.Enumerator it = mPoints.GetEnumerator(); it.MoveNext(); ++it) foreach (var it in mPoints) { s.addPoint(it.x, it.y); } if (mClosed) s.close(); return s; }
//----------------------------------------------------------------------- void parsePolygon(ref MultiShape @out, XmlNode pPolygonNode) { //if (pPolygonNode->first_attribute("points")) if (pPolygonNode.Attributes["points"] != null) { //if (pPolygonNode->first_attribute("points")->value_size() < 3) return; if (string.IsNullOrEmpty(pPolygonNode.Attributes["points"].Value)) return; if (pPolygonNode.Attributes["points"].Value.Length < 3) return; string temp = xtrim(pPolygonNode.Attributes["points"].Value); std_vector<string> pts = split(temp, " "); if (pts.size() == 0) return; Shape s = new Shape(); for (int i = 0; i < pts.size() - 1; i += 2) s.addPoint(parseReal(pts[i + 0]), parseReal(pts[i + 1])); if (s.getPointsReference().size() == 0) return; s.close(); // if(pPolygonNode->first_attribute("id")) // ss.id = pPolygonNode->first_attribute("id")->value(); s.translate(getAttribTranslate(pPolygonNode)); @out.addShape(s); } }
// * // * Build a MultiShape from chars (one Shape per character) // * \exception Ogre::InternalErrorException Freetype error // * \todo Need to split shapes of multi region chars. For example the letter \c O // * has two shapes, but they are connected to one shape. // public MultiShape realizeShapes() { MultiShape retVal = new MultiShape(); FT_Library ftlib = new FT_Library(); FT_Face face = new FT_Face(); FT_GlyphSlot slot = new FT_GlyphSlot(); FT_Error error = FT_Init_FreeType(ftlib); if (error == 0) { error = FT_New_Face(ftlib, getFontFileByName().c_str(), 0, face); if (error == FT_Err_Unknown_File_Format) { //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __LINE__ macro: //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __FILE__ macro: throw ExceptionFactory.create(Mogre.ExceptionCodeType<Mogre.Exception.ExceptionCodes.ERR_INTERNAL_ERROR>(), "FreeType ERROR: FT_Err_Unknown_File_Format", "Procedural::TextShape::realizeShapes()", __FILE__, __LINE__); ; } else if (error != null) { //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __LINE__ macro: //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __FILE__ macro: throw ExceptionFactory.create(Mogre.ExceptionCodeType<Mogre.Exception.ExceptionCodes.ERR_INTERNAL_ERROR>(), "FreeType ERROR: FT_New_Face - " + StringConverter.toString(error), "Procedural::TextShape::realizeShapes()", __FILE__, __LINE__); ; } else { FT_Set_Pixel_Sizes(face, 0, mFontSize); int px = 0; int py = 0; slot = face.glyph; for (int n = 0; n < mText.length(); n++) { error = FT_Load_Char(face, mText[n], FT_LOAD_NO_BITMAP); if (error != null) continue; Shape s = new Shape(); int nContours = face.glyph.outline.n_contours; int startPos = 0; string tags = face.glyph.outline.tags; FT_Vector[] vec = face.glyph.outline.points; for (int k = 0; k < nContours; k++) { if (k > 0) startPos = face.glyph.outline.contours[k-1]+1; int endPos = face.glyph.outline.contours[k]+1; Vector2 lastPoint = Vector2.ZERO; for (int j = startPos; j < endPos; j++) { if (FT_CURVE_TAG(tags[j]) == FT_CURVE_TAG_ON) { lastPoint = Vector2((float)vec[j].x, (float)vec[j].y); s.addPoint(lastPoint / 64.0f); } else { if (FT_CURVE_TAG(tags[j]) == FT_CURVE_TAG_CUBIC) { int prevPoint = j - 1; if (j == 0) prevPoint = endPos - 1; int nextIndex = j + 1; if (nextIndex >= endPos) nextIndex = startPos; Vector2[] nextPoint = new Vector2[nextIndex]((float)vec.x, (float)vec[nextIndex].y); if ((FT_CURVE_TAG(tags[prevPoint]) != FT_CURVE_TAG_ON) && (FT_CURVE_TAG(tags[prevPoint]) == FT_CURVE_TAG_CUBIC)) { BezierCurve2 bc = new BezierCurve2(); bc.addPoint(Vector2((float)vec[prevPoint].x, (float)vec[prevPoint].y) / 64.0f); bc.addPoint(Vector2((float)vec[j].x, (float)vec[j].y) / 64.0f); bc.addPoint(Vector2((float)vec[nextIndex].x, (float)vec[nextIndex].y) / 64.0f); s.appendShape(bc.realizeShape()); } } else { Vector2[] conicPoint = new Vector2[j]((float)vec.x, (float)vec[j].y); if (j == startPos) { if ((FT_CURVE_TAG(tags[endPos-1]) != FT_CURVE_TAG_ON) && (FT_CURVE_TAG(tags[endPos-1]) != FT_CURVE_TAG_CUBIC)) { Vector2[] lastConnic = new Vector2[endPos - 1]((float)vec.x, (float)vec[endPos - 1].y); lastPoint = (conicPoint + lastConnic) / 2; } } int nextIndex = j + 1; if (nextIndex >= endPos) nextIndex = startPos; Vector2[] nextPoint = new Vector2[nextIndex]((float)vec.x, (float)vec[nextIndex].y); bool nextIsConnic = (FT_CURVE_TAG(tags[nextIndex]) != FT_CURVE_TAG_ON) && (FT_CURVE_TAG(tags[nextIndex]) != FT_CURVE_TAG_CUBIC); if (nextIsConnic) nextPoint = (conicPoint + nextPoint) / 2; int pc = s.getPointCount(); BezierCurve2 bc = new BezierCurve2(); if (pc == 0) bc.addPoint(Vector2.ZERO); else bc.addPoint(s.getPoint(pc - 1)); bc.addPoint(lastPoint / 64.0f); bc.addPoint(conicPoint / 64.0f); bc.addPoint(nextPoint / 64.0f); if (pc == 0) s.appendShape(bc.realizeShape()); else { List<Vector2> subShape = bc.realizeShape().getPoints(); for (List<Vector2>.Enumerator iter = subShape.GetEnumerator(); iter.MoveNext(); iter++) { if (iter != subShape.GetEnumerator()) s.addPoint(iter.Current); } } if (nextIsConnic) // //ORIGINAL LINE: lastPoint = nextPoint; lastPoint=(nextPoint); } } } } s.close(); s.translate((float)px, (float)py); retVal.addShape(s); px += slot.advance.x >> 6; py += slot.advance.y >> 6; } FT_Done_Face(face); } FT_Done_FreeType(ftlib); } else { //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __LINE__ macro: //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __FILE__ macro: throw ExceptionFactory.create(Mogre.ExceptionCodeType<Mogre.Exception.ExceptionCodes.ERR_INTERNAL_ERROR>(), "FreeType ERROR: FT_Init_FreeTyp", "Procedural::TextShape::realizeShapes()", __FILE__, __LINE__); ; } return retVal; }