index e6f7acb0c17319f396099b5d529e724ea43651b6..7c741ac4ce466838da20f4a2a6bc895e08c0075d 100644 (file)
}
}
+#define POINT_RELATION_TO_AREA(pt, area) ((pt)[0] < (area)->x0 ? 1 : ((pt)[0] > (area)->x1 ? 2 : ((pt)[1] < (area)->y0 ? 3 : ((pt)[1] > (area)->y1 ? 4 : 0))))
+
+void Path::Convert(NRRectL *area, double treshhold)
+{
+ if ( descr_flags & descr_adding_bezier ) {
+ CancelBezier();
+ }
+
+ if ( descr_flags & descr_doing_subpath ) {
+ CloseSubpath();
+ }
+
+ SetBackData(false);
+ ResetPoints();
+ if ( descr_cmd.empty() ) {
+ return;
+ }
+
+ NR::Point curX;
+ int curP = 1;
+ int lastMoveTo = 0;
+ short last_point_relation = 0;
+ short curent_point_relation = 0;
+ bool last_start_elimination = false;
+ bool start_elimination = false;
+ bool replace = false;
+
+ // first point
+ {
+ int const firstTyp = descr_cmd[0]->getType();
+ if ( firstTyp == descr_moveto ) {
+ curX = dynamic_cast<PathDescrMoveTo *>(descr_cmd[0])->p;
+ } else {
+ curP = 0;
+ curX[0] = curX[1] = 0;
+ }
+
+ last_point_relation = POINT_RELATION_TO_AREA(curX, area);
+ lastMoveTo = AddPoint(curX, true);
+ }
+ descr_cmd[0]->associated = lastMoveTo;
+
+ // process nodes one by one
+ while ( curP < int(descr_cmd.size()) ) {
+
+ int const nType = descr_cmd[curP]->getType();
+ NR::Point nextX;
+
+ switch (nType) {
+ case descr_forced: {
+ descr_cmd[curP]->associated = AddForcedPoint(curX);
+ last_point_relation = 0;
+ curP++;
+ break;
+ }
+
+ case descr_moveto: {
+ PathDescrMoveTo *nData = dynamic_cast<PathDescrMoveTo *>(descr_cmd[curP]);
+ nextX = nData->p;
+ lastMoveTo = AddPoint(nextX, true);
+ descr_cmd[curP]->associated = lastMoveTo;
+ last_point_relation = POINT_RELATION_TO_AREA(nextX, area);
+ start_elimination = false;
+
+ curP++;
+ break;
+ }
+
+ case descr_close: {
+ nextX = pts[lastMoveTo].p;
+ descr_cmd[curP]->associated = AddPoint(nextX, false);
+ if ( descr_cmd[curP]->associated < 0 ) {
+ if ( curP == 0 ) {
+ descr_cmd[curP]->associated = 0;
+ } else {
+ descr_cmd[curP]->associated = descr_cmd[curP - 1]->associated;
+ }
+ }
+ last_point_relation = 0;
+ curP++;
+ break;
+ }
+
+ case descr_lineto: {
+ PathDescrLineTo *nData = dynamic_cast<PathDescrLineTo *>(descr_cmd[curP]);
+ nextX = nData->p;
+ curent_point_relation = POINT_RELATION_TO_AREA(nextX, area);
+ replace = false;
+ last_start_elimination = start_elimination;
+ if (curent_point_relation > 0 && curent_point_relation == last_point_relation) {
+ if (!start_elimination) {
+ start_elimination = true;
+ } else {
+ replace = true;
+ descr_cmd[curP]->associated = ReplacePoint(nextX);
+ }
+ } else {
+ start_elimination = false;
+ }
+
+ if (!replace) {
+ descr_cmd[curP]->associated = AddPoint(nextX, false);
+ }
+
+ if ( descr_cmd[curP]->associated < 0 ) {
+ // point is not added as position is equal to the last added
+ start_elimination = last_start_elimination;
+ if ( curP == 0 ) {
+ descr_cmd[curP]->associated = 0;
+ } else {
+ descr_cmd[curP]->associated = descr_cmd[curP - 1]->associated;
+ }
+ }
+ last_point_relation = curent_point_relation;
+ curP++;
+ break;
+ }
+
+ case descr_cubicto: {
+ PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(descr_cmd[curP]);
+ nextX = nData->p;
+
+ curent_point_relation = POINT_RELATION_TO_AREA(nextX, area);
+ replace = false;
+ last_start_elimination = start_elimination;
+ if (curent_point_relation > 0 && curent_point_relation == last_point_relation &&
+ curent_point_relation == POINT_RELATION_TO_AREA(curX + (nData->start), area) &&
+ curent_point_relation == POINT_RELATION_TO_AREA(nextX + (nData->end), area))
+ {
+ if (!start_elimination) {
+ start_elimination = true;
+ } else {
+ replace = true;
+ descr_cmd[curP]->associated = ReplacePoint(nextX);
+ }
+ } else {
+ start_elimination = false;
+ }
+
+ if (!replace) {
+ RecCubicTo(curX, nData->start, nextX, nData->end, treshhold, 8);
+ descr_cmd[curP]->associated = AddPoint(nextX,false);
+ }
+
+ if ( descr_cmd[curP]->associated < 0 ) {
+ // point is not added as position is equal to the last added
+ start_elimination = last_start_elimination;
+ if ( curP == 0 ) {
+ descr_cmd[curP]->associated = 0;
+ } else {
+ descr_cmd[curP]->associated = descr_cmd[curP - 1]->associated;
+ }
+ }
+ last_point_relation = curent_point_relation;
+ curP++;
+ break;
+ }
+
+ case descr_arcto: {
+ PathDescrArcTo *nData = dynamic_cast<PathDescrArcTo *>(descr_cmd[curP]);
+ nextX = nData->p;
+ DoArc(curX, nextX, nData->rx, nData->ry, nData->angle, nData->large, nData->clockwise, treshhold);
+ descr_cmd[curP]->associated = AddPoint(nextX, false);
+ if ( descr_cmd[curP]->associated < 0 ) {
+ if ( curP == 0 ) {
+ descr_cmd[curP]->associated = 0;
+ } else {
+ descr_cmd[curP]->associated = descr_cmd[curP - 1]->associated;
+ }
+ }
+ last_point_relation = 0;
+
+ curP++;
+ break;
+ }
+
+ case descr_bezierto: {
+ PathDescrBezierTo *nBData = dynamic_cast<PathDescrBezierTo *>(descr_cmd[curP]);
+ int nbInterm = nBData->nb;
+ nextX = nBData->p;
+ int curBD = curP;
+
+ curP++;
+ int ip = curP;
+ PathDescrIntermBezierTo *nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[ip]);
+
+ if ( nbInterm == 1 ) {
+ NR::Point const midX = nData->p;
+ RecBezierTo(midX, curX, nextX, treshhold, 8);
+ } else if ( nbInterm > 1 ) {
+ NR::Point bx = curX;
+ NR::Point cx = curX;
+ NR::Point dx = curX;
+
+ dx = nData->p;
+ ip++;
+ nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[ip]);
+
+ cx = 2 * bx - dx;
+
+ for (int k = 0; k < nbInterm - 1; k++) {
+ bx = cx;
+ cx = dx;
+
+ dx = nData->p;
+ ip++;
+ nData = dynamic_cast<PathDescrIntermBezierTo *>(descr_cmd[ip]);
+
+ NR::Point stx = (bx + cx) / 2;
+ if ( k > 0 ) {
+ descr_cmd[ip - 2]->associated = AddPoint(stx, false);
+ if ( descr_cmd[ip - 2]->associated < 0 ) {
+ if ( curP == 0 ) {
+ descr_cmd[ip - 2]->associated = 0;
+ } else {
+ descr_cmd[ip - 2]->associated = descr_cmd[ip - 3]->associated;
+ }
+ }
+ }
+
+ {
+ NR::Point const mx = (cx + dx) / 2;
+ RecBezierTo(cx, stx, mx, treshhold, 8);
+ }
+ }
+
+ {
+ bx = cx;
+ cx = dx;
+
+ dx = nextX;
+ dx = 2 * dx - cx;
+
+ NR::Point stx = (bx + cx) / 2;
+
+ descr_cmd[ip - 1]->associated = AddPoint(stx, false);
+ if ( descr_cmd[ip - 1]->associated < 0 ) {
+ if ( curP == 0 ) {
+ descr_cmd[ip - 1]->associated = 0;
+ } else {
+ descr_cmd[ip - 1]->associated = descr_cmd[ip - 2]->associated;
+ }
+ }
+
+ {
+ NR::Point mx = (cx + dx) / 2;
+ RecBezierTo(cx, stx, mx, treshhold, 8);
+ }
+ }
+ }
+
+ descr_cmd[curBD]->associated = AddPoint(nextX, false);
+ if ( descr_cmd[curBD]->associated < 0 ) {
+ if ( curP == 0 ) {
+ descr_cmd[curBD]->associated = 0;
+ } else {
+ descr_cmd[curBD]->associated = descr_cmd[curBD - 1]->associated;
+ }
+ }
+
+ last_point_relation = 0;
+
+ curP += nbInterm;
+ break;
+ }
+ }
+
+ curX = nextX;
+ }
+}
void Path::ConvertEvenLines(double treshhold)