| 139 | } |
| 140 | |
| 141 | void svgDraw(NVGcontext* vg, NSVGimage* svg) { |
| 142 | DEBUG_ONLY(printf("new image: %g x %g px\n", svg->width, svg->height);) |
| 143 | int shapeIndex = 0; |
| 144 | // Iterate shape linked list |
| 145 | for (NSVGshape* shape = svg->shapes; shape; shape = shape->next, shapeIndex++) { |
| 146 | DEBUG_ONLY(printf(" new shape: %d id \"%s\", fillrule %d, from (%f, %f) to (%f, %f)\n", shapeIndex, shape->id, shape->fillRule, shape->bounds[0], shape->bounds[1], shape->bounds[2], shape->bounds[3]);) |
| 147 | |
| 148 | // Visibility |
| 149 | if (!(shape->flags & NSVG_FLAGS_VISIBLE)) |
| 150 | continue; |
| 151 | |
| 152 | nvgSave(vg); |
| 153 | |
| 154 | // Opacity |
| 155 | if (shape->opacity < 1.0) |
| 156 | nvgAlpha(vg, shape->opacity); |
| 157 | |
| 158 | // Build path |
| 159 | nvgBeginPath(vg); |
| 160 | |
| 161 | // Iterate path linked list |
| 162 | for (NSVGpath* path = shape->paths; path; path = path->next) { |
| 163 | DEBUG_ONLY(printf(" new path: %d points, %s, from (%f, %f) to (%f, %f)\n", path->npts, path->closed ? "closed" : "open", path->bounds[0], path->bounds[1], path->bounds[2], path->bounds[3]);) |
| 164 | |
| 165 | nvgMoveTo(vg, path->pts[0], path->pts[1]); |
| 166 | for (int i = 1; i < path->npts; i += 3) { |
| 167 | float* p = &path->pts[2 * i]; |
| 168 | nvgBezierTo(vg, p[0], p[1], p[2], p[3], p[4], p[5]); |
| 169 | // nvgLineTo(vg, p[4], p[5]); |
| 170 | DEBUG_ONLY(printf(" bezier (%f, %f) to (%f, %f)\n", p[-2], p[-1], p[4], p[5]);) |
| 171 | } |
| 172 | |
| 173 | // Close path |
| 174 | if (path->closed) |
| 175 | nvgClosePath(vg); |
| 176 | |
| 177 | // Compute whether this is a hole or a solid. |
| 178 | // Assume that no paths are crossing (usually true for normal SVG graphics). |
| 179 | // Also assume that the topology is the same if we use straight lines rather than Beziers (not always the case but usually true). |
| 180 | // Using the even-odd fill rule, if we draw a line from a point on the path to a point outside the boundary (e.g. top left) and count the number of times it crosses another path, the parity of this count determines whether the path is a hole (odd) or solid (even). |
| 181 | int crossings = 0; |
| 182 | math::Vec p0 = math::Vec(path->pts[0], path->pts[1]); |
| 183 | math::Vec p1 = math::Vec(path->bounds[0] - 1.0, path->bounds[1] - 1.0); |
| 184 | // Iterate all other paths |
| 185 | for (NSVGpath* path2 = shape->paths; path2; path2 = path2->next) { |
| 186 | if (path2 == path) |
| 187 | continue; |
| 188 | |
| 189 | // Iterate all lines on the path |
| 190 | if (path2->npts < 4) |
| 191 | continue; |
| 192 | for (int i = 1; i < path2->npts + 3; i += 3) { |
| 193 | float* p = &path2->pts[2 * i]; |
| 194 | // The previous point |
| 195 | math::Vec p2 = math::Vec(p[-2], p[-1]); |
| 196 | // The current point |
| 197 | math::Vec p3 = (i < path2->npts) ? math::Vec(p[4], p[5]) : math::Vec(path2->pts[0], path2->pts[1]); |
| 198 | float crossing = getLineCrossing(p0, p1, p2, p3); |
no test coverage detected