ReactOS 0.4.17-dev-923-g4c9a150
geometry.c
Go to the documentation of this file.
1/*
2 * Copyright 2015 Henri Verbeet for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include "d2d1_private.h"
20#include <float.h>
21
23
24#define D2D_FIGURE_FLAG_CLOSED 0x00000001u
25#define D2D_FIGURE_FLAG_HOLLOW 0x00000002u
26
27#define D2D_CDT_EDGE_FLAG_FREED 0x80000000u
28#define D2D_CDT_EDGE_FLAG_VISITED(r) (1u << (r))
29
30#define D2D_FP_EPS (1.0f / (1 << FLT_MANT_DIG))
31
33{{{
34 1.0f, 0.0f,
35 0.0f, 1.0f,
36 0.0f, 0.0f,
37}}};
38
40{
45};
46
48{
54};
55
57{
58 size_t figure_idx;
59 size_t vertex_idx;
61};
62
64{
70
74
78
80 unsigned int flags;
81};
82
84{
85 size_t idx;
87};
88
90{
92 size_t vertex[2];
93 unsigned int flags;
94};
95
96struct d2d_cdt
97{
99 size_t edges_size;
101 size_t free_edge;
102
104};
105
107{
111 float t;
113};
114
116{
120};
121
123{
124 float x[2];
125 float y[2];
126};
127
129{
130 float *now, *other;
131 size_t length;
132};
133
135 const D2D1_POINT_2F *p, float u, float v, float sign)
136{
137 b->position = *p;
138 b->texcoord.u = u;
139 b->texcoord.v = v;
140 b->texcoord.sign = sign;
141}
142
144{
145 f->v[0] = v0;
146 f->v[1] = v1;
147 f->v[2] = v2;
148}
149
150static void d2d_outline_vertex_set(struct d2d_outline_vertex *v, float x, float y,
151 float prev_x, float prev_y, float next_x, float next_y)
152{
153 d2d_point_set(&v->position, x, y);
154 d2d_point_set(&v->prev, prev_x, prev_y);
155 d2d_point_set(&v->next, next_x, next_y);
156}
157
159 const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2,
160 float prev_x, float prev_y, float next_x, float next_y)
161{
162 a->position = *position;
163 a->p0 = *p0;
164 a->p1 = *p1;
165 a->p2 = *p2;
166 d2d_point_set(&a->prev, prev_x, prev_y);
167 d2d_point_set(&a->next, next_x, next_y);
168}
169
170static void d2d_fp_two_sum(float *out, float a, float b)
171{
172 float a_virt, a_round, b_virt, b_round;
173
174 out[1] = a + b;
175 b_virt = out[1] - a;
176 a_virt = out[1] - b_virt;
177 b_round = b - b_virt;
178 a_round = a - a_virt;
179 out[0] = a_round + b_round;
180}
181
182static void d2d_fp_fast_two_sum(float *out, float a, float b)
183{
184 float b_virt;
185
186 out[1] = a + b;
187 b_virt = out[1] - a;
188 out[0] = b - b_virt;
189}
190
191static void d2d_fp_two_two_sum(float *out, const float *a, const float *b)
192{
193 float sum[2];
194
195 d2d_fp_two_sum(out, a[0], b[0]);
196 d2d_fp_two_sum(sum, a[1], out[1]);
197 d2d_fp_two_sum(&out[1], sum[0], b[1]);
198 d2d_fp_two_sum(&out[2], sum[1], out[2]);
199}
200
201static void d2d_fp_two_diff_tail(float *out, float a, float b, float x)
202{
203 float a_virt, a_round, b_virt, b_round;
204
205 b_virt = a - x;
206 a_virt = x + b_virt;
207 b_round = b_virt - b;
208 a_round = a - a_virt;
209 *out = a_round + b_round;
210}
211
212static void d2d_fp_two_two_diff(float *out, const float *a, const float *b)
213{
214 float sum[2], diff;
215
216 diff = a[0] - b[0];
217 d2d_fp_two_diff_tail(out, a[0], b[0], diff);
218 d2d_fp_two_sum(sum, a[1], diff);
219 diff = sum[0] - b[1];
220 d2d_fp_two_diff_tail(&out[1], sum[0], b[1], diff);
221 d2d_fp_two_sum(&out[2], sum[1], diff);
222}
223
224static void d2d_fp_split(float *out, float a)
225{
226 float a_big, c;
227
228 c = a * ((1 << (FLT_MANT_DIG / 2)) + 1.0f);
229 a_big = c - a;
230 out[1] = c - a_big;
231 out[0] = a - out[1];
232}
233
234static void d2d_fp_two_product_presplit(float *out, float a, float b, const float *b_split)
235{
236 float a_split[2], err1, err2, err3;
237
238 out[1] = a * b;
239 d2d_fp_split(a_split, a);
240 err1 = out[1] - (a_split[1] * b_split[1]);
241 err2 = err1 - (a_split[0] * b_split[1]);
242 err3 = err2 - (a_split[1] * b_split[0]);
243 out[0] = (a_split[0] * b_split[0]) - err3;
244}
245
246static void d2d_fp_two_product(float *out, float a, float b)
247{
248 float b_split[2];
249
250 d2d_fp_split(b_split, b);
252}
253
254static void d2d_fp_square(float *out, float a)
255{
256 float a_split[2], err1, err2;
257
258 out[1] = a * a;
259 d2d_fp_split(a_split, a);
260 err1 = out[1] - (a_split[1] * a_split[1]);
261 err2 = err1 - ((a_split[1] + a_split[1]) * a_split[0]);
262 out[0] = (a_split[0] * a_split[0]) - err2;
263}
264
265static float d2d_fp_estimate(float *a, size_t len)
266{
267 float out = a[0];
268 size_t idx = 1;
269
270 while (idx < len)
271 out += a[idx++];
272
273 return out;
274}
275
276static void d2d_fp_fast_expansion_sum_zeroelim(float *out, size_t *out_len,
277 const float *a, size_t a_len, const float *b, size_t b_len)
278{
279 float sum[2], q, a_curr, b_curr;
280 size_t a_idx, b_idx, out_idx;
281
282 a_curr = a[0];
283 b_curr = b[0];
284 a_idx = b_idx = 0;
285 if ((b_curr > a_curr) == (b_curr > -a_curr))
286 {
287 q = a_curr;
288 a_curr = a[++a_idx];
289 }
290 else
291 {
292 q = b_curr;
293 b_curr = b[++b_idx];
294 }
295 out_idx = 0;
296 if (a_idx < a_len && b_idx < b_len)
297 {
298 if ((b_curr > a_curr) == (b_curr > -a_curr))
299 {
300 d2d_fp_fast_two_sum(sum, a_curr, q);
301 a_curr = a[++a_idx];
302 }
303 else
304 {
305 d2d_fp_fast_two_sum(sum, b_curr, q);
306 b_curr = b[++b_idx];
307 }
308 if (sum[0] != 0.0f)
309 out[out_idx++] = sum[0];
310 q = sum[1];
311 while (a_idx < a_len && b_idx < b_len)
312 {
313 if ((b_curr > a_curr) == (b_curr > -a_curr))
314 {
315 d2d_fp_two_sum(sum, q, a_curr);
316 a_curr = a[++a_idx];
317 }
318 else
319 {
320 d2d_fp_two_sum(sum, q, b_curr);
321 b_curr = b[++b_idx];
322 }
323 if (sum[0] != 0.0f)
324 out[out_idx++] = sum[0];
325 q = sum[1];
326 }
327 }
328 while (a_idx < a_len)
329 {
330 d2d_fp_two_sum(sum, q, a_curr);
331 a_curr = a[++a_idx];
332 if (sum[0] != 0.0f)
333 out[out_idx++] = sum[0];
334 q = sum[1];
335 }
336 while (b_idx < b_len)
337 {
338 d2d_fp_two_sum(sum, q, b_curr);
339 b_curr = b[++b_idx];
340 if (sum[0] != 0.0f)
341 out[out_idx++] = sum[0];
342 q = sum[1];
343 }
344 if (q != 0.0f || !out_idx)
345 out[out_idx++] = q;
346
347 *out_len = out_idx;
348}
349
350static void d2d_fp_scale_expansion_zeroelim(float *out, size_t *out_len, const float *a, size_t a_len, float b)
351{
352 float product[2], sum[2], b_split[2], q[2], a_curr;
353 size_t a_idx, out_idx;
354
355 d2d_fp_split(b_split, b);
356 d2d_fp_two_product_presplit(q, a[0], b, b_split);
357 out_idx = 0;
358 if (q[0] != 0.0f)
359 out[out_idx++] = q[0];
360 for (a_idx = 1; a_idx < a_len; ++a_idx)
361 {
362 a_curr = a[a_idx];
363 d2d_fp_two_product_presplit(product, a_curr, b, b_split);
364 d2d_fp_two_sum(sum, q[1], product[0]);
365 if (sum[0] != 0.0f)
366 out[out_idx++] = sum[0];
367 d2d_fp_fast_two_sum(q, product[1], sum[1]);
368 if (q[0] != 0.0f)
369 out[out_idx++] = q[0];
370 }
371 if (q[1] != 0.0f || !out_idx)
372 out[out_idx++] = q[1];
373
374 *out_len = out_idx;
375}
376
378 const D2D1_POINT_2F *a, const D2D1_POINT_2F *b)
379{
380 out->x = a->x - b->x;
381 out->y = a->y - b->y;
382}
383
385{
386 p->x *= scale;
387 p->y *= scale;
388}
389
391 const D2D1_POINT_2F *a, const D2D1_POINT_2F *b, float t)
392{
393 out->x = a->x * (1.0f - t) + b->x * t;
394 out->y = a->y * (1.0f - t) + b->y * t;
395}
396
398 const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2, float t)
399{
400 float t_c = 1.0f - t;
401
402 out->x = t_c * (t_c * p0->x + t * p1->x) + t * (t_c * p1->x + t * p2->x);
403 out->y = t_c * (t_c * p0->y + t * p1->y) + t * (t_c * p1->y + t * p2->y);
404}
405
406static float d2d_point_length(const D2D1_POINT_2F *p)
407{
408 return sqrtf(d2d_point_dot(p, p));
409}
410
412{
413 float l;
414
415 if ((l = d2d_point_length(p)) != 0.0f)
416 d2d_point_scale(p, 1.0f / l);
417}
418
420{
422}
423
425{
427}
428
429/* This implementation is based on the paper "Adaptive Precision
430 * Floating-Point Arithmetic and Fast Robust Geometric Predicates" and
431 * associated (Public Domain) code by Jonathan Richard Shewchuk. */
432static float d2d_point_ccw(const D2D1_POINT_2F *a, const D2D1_POINT_2F *b, const D2D1_POINT_2F *c)
433{
434 static const float err_bound_result = (3.0f + 8.0f * D2D_FP_EPS) * D2D_FP_EPS;
435 static const float err_bound_a = (3.0f + 16.0f * D2D_FP_EPS) * D2D_FP_EPS;
436 static const float err_bound_b = (2.0f + 12.0f * D2D_FP_EPS) * D2D_FP_EPS;
437 static const float err_bound_c = (9.0f + 64.0f * D2D_FP_EPS) * D2D_FP_EPS * D2D_FP_EPS;
438 float det_d[16], det_c2[12], det_c1[8], det_b[4], temp4[4], temp2a[2], temp2b[2], abxacy[2], abyacx[2];
439 size_t det_d_len, det_c2_len, det_c1_len;
440 float det, det_sum, err_bound;
441 struct d2d_fp_two_vec2 ab, ac;
442
443 ab.x[1] = b->x - a->x;
444 ab.y[1] = b->y - a->y;
445 ac.x[1] = c->x - a->x;
446 ac.y[1] = c->y - a->y;
447
448 abxacy[1] = ab.x[1] * ac.y[1];
449 abyacx[1] = ab.y[1] * ac.x[1];
450 det = abxacy[1] - abyacx[1];
451
452 if (abxacy[1] > 0.0f)
453 {
454 if (abyacx[1] <= 0.0f)
455 return det;
456 det_sum = abxacy[1] + abyacx[1];
457 }
458 else if (abxacy[1] < 0.0f)
459 {
460 if (abyacx[1] >= 0.0f)
461 return det;
462 det_sum = -abxacy[1] - abyacx[1];
463 }
464 else
465 {
466 return det;
467 }
468
469 err_bound = err_bound_a * det_sum;
470 if (det >= err_bound || -det >= err_bound)
471 return det;
472
473 d2d_fp_two_product(abxacy, ab.x[1], ac.y[1]);
474 d2d_fp_two_product(abyacx, ab.y[1], ac.x[1]);
475 d2d_fp_two_two_diff(det_b, abxacy, abyacx);
476
477 det = d2d_fp_estimate(det_b, 4);
478 err_bound = err_bound_b * det_sum;
479 if (det >= err_bound || -det >= err_bound)
480 return det;
481
482 d2d_fp_two_diff_tail(&ab.x[0], b->x, a->x, ab.x[1]);
483 d2d_fp_two_diff_tail(&ab.y[0], b->y, a->y, ab.y[1]);
484 d2d_fp_two_diff_tail(&ac.x[0], c->x, a->x, ac.x[1]);
485 d2d_fp_two_diff_tail(&ac.y[0], c->y, a->y, ac.y[1]);
486
487 if (ab.x[0] == 0.0f && ab.y[0] == 0.0f && ac.x[0] == 0.0f && ac.y[0] == 0.0f)
488 return det;
489
490 err_bound = err_bound_c * det_sum + err_bound_result * fabsf(det);
491 det += (ab.x[1] * ac.y[0] + ac.y[1] * ab.x[0]) - (ab.y[1] * ac.x[0] + ac.x[1] * ab.y[0]);
492 if (det >= err_bound || -det >= err_bound)
493 return det;
494
495 d2d_fp_two_product(temp2a, ab.x[0], ac.y[1]);
496 d2d_fp_two_product(temp2b, ab.y[0], ac.x[1]);
497 d2d_fp_two_two_diff(temp4, temp2a, temp2b);
498 d2d_fp_fast_expansion_sum_zeroelim(det_c1, &det_c1_len, det_b, 4, temp4, 4);
499
500 d2d_fp_two_product(temp2a, ab.x[1], ac.y[0]);
501 d2d_fp_two_product(temp2b, ab.y[1], ac.x[0]);
502 d2d_fp_two_two_diff(temp4, temp2a, temp2b);
503 d2d_fp_fast_expansion_sum_zeroelim(det_c2, &det_c2_len, det_c1, det_c1_len, temp4, 4);
504
505 d2d_fp_two_product(temp2a, ab.x[0], ac.y[0]);
506 d2d_fp_two_product(temp2b, ab.y[0], ac.x[0]);
507 d2d_fp_two_two_diff(temp4, temp2a, temp2b);
508 d2d_fp_fast_expansion_sum_zeroelim(det_d, &det_d_len, det_c2, det_c2_len, temp4, 4);
509
510 return det_d[det_d_len - 1];
511}
512
513/* Determine whether the point q is within the given tolerance of the line
514 * segment defined by p0 and p1, with the given stroke width and transform.
515 * Note that we don't care about the tolerance with respect to end-points or
516 * joins here; those are handled separately. */
518 const D2D1_POINT_2F *p1, const D2D1_MATRIX_3X2_F *transform, float stroke_width, float tolerance)
519{
520 D2D1_POINT_2F v_n, v_p, v_q, v_r;
521 float l;
522
523 d2d_point_subtract(&v_p, p1, p0);
524 if ((l = d2d_point_length(&v_p)) == 0.0f)
525 return FALSE;
526
527 /* After (shear) transformation, the line segment is a parallelogram
528 * defined by p⃑' and n⃑':
529 *
530 * p⃑ = P₁ - P₀
531 * n⃑ = wp̂⟂
532 * p⃑' = p⃑T
533 * n⃑' = n⃑T */
534 l = stroke_width / l;
535 d2d_point_set(&v_r, transform->_31, transform->_32);
536 d2d_point_transform(&v_n, transform, -v_p.y * l, v_p.x * l);
537 d2d_point_subtract(&v_n, &v_n, &v_r);
538 d2d_point_transform(&v_p, transform, v_p.x, v_p.y);
539 d2d_point_subtract(&v_p, &v_p, &v_r);
540
541 /* Decompose the vector q⃑ = Q - P₀T into a linear combination of
542 * p⃑' and n⃑':
543 *
544 * lq⃑ = xp⃑' + yn⃑' */
545 d2d_point_transform(&v_q, transform, p0->x, p0->y);
546 d2d_point_subtract(&v_q, q, &v_q);
547 l = v_p.x * v_n.y - v_p.y * v_n.x;
548 v_r.x = v_q.x * v_n.y - v_q.y * v_n.x;
549 v_r.y = v_q.x * v_p.y - v_q.y * v_p.x;
550
551 if (l < 0.0f)
552 {
553 l *= -1.0f;
554 v_r.x *= -1.0f;
555 }
556
557 /* Check where Q projects onto p⃑'. */
558 if (v_r.x < 0.0f || v_r.x > l)
559 return FALSE;
560
561 /* Check where Q projects onto n⃑'. */
562 if (fabs(v_r.y) < l)
563 return TRUE;
564
565 /* Q lies outside the segment. Check whether the distance to the edge is
566 * within the tolerance.
567 *
568 * P₀' = P₀T + n⃑'
569 * q⃑' = Q - P₀'
570 * = q⃑ - n⃑'
571 *
572 * The distance is then q⃑' · p̂'⟂. */
573
574 if (v_r.y > 0.0f)
575 d2d_point_scale(&v_n, -1.0f);
576 d2d_point_subtract(&v_q, &v_q, &v_n);
577
578 /* Check where Q projects onto p⃑' + n⃑'. */
579 l = d2d_point_dot(&v_q, &v_p);
580 if (l < 0.0f || l > d2d_point_dot(&v_p, &v_p))
581 return FALSE;
582
583 v_n.x = -v_p.y;
584 v_n.y = v_p.x;
586
587 return fabsf(d2d_point_dot(&v_q, &v_n)) < tolerance;
588}
589
590/* Approximate the Bézier segment with a (wide) line segment. If the point
591 * lies outside the approximation, we're done. If the width of the
592 * approximation is less than the tolerance and the point lies inside, we're
593 * also done. If neither of those is the case, we subdivide the Bézier segment
594 * and try again. */
596 const D2D1_BEZIER_SEGMENT *b, const D2D1_MATRIX_3X2_F *transform, float stroke_width, float tolerance)
597{
598 float d1, d2, d3, d4, d, l, m, w, w2;
599 D2D1_POINT_2F t[7], start, end, v_p;
601
602 m = 1.0f;
603 w = stroke_width * 0.5f;
604
605 d2d_point_subtract(&v_p, &b->point3, p0);
606 /* If the endpoints coincide, use the line through the control points as
607 * the direction vector. That choice is somewhat arbitrary; other choices
608 * with tighter error bounds exist. */
609 if ((l = d2d_point_dot(&v_p, &v_p)) == 0.0f)
610 {
611 d2d_point_subtract(&v_p, &b->point2, &b->point1);
612 /* If the control points also coincide, the curve is in fact a line. */
613 if ((l = d2d_point_dot(&v_p, &v_p)) == 0.0f)
614 {
615 d2d_point_subtract(&v_p, &b->point1, p0);
616 end.x = p0->x + 0.75f * v_p.x;
617 end.y = p0->y + 0.75f * v_p.y;
618
619 return d2d_point_on_line_segment(q, p0, &end, transform, w, tolerance);
620 }
621 m = 0.0f;
622 }
623 l = sqrtf(l);
624 d2d_point_scale(&v_p, 1.0f / l);
625 m *= l;
626
627 /* Calculate the width w2 of the approximation. */
628
629 end.x = p0->x + v_p.x;
630 end.y = p0->y + v_p.y;
631 /* Here, d1 and d2 are the maximum (signed) distance of the control points
632 * from the line through the start and end points. */
633 d1 = d2d_point_ccw(p0, &end, &b->point1);
634 d2 = d2d_point_ccw(p0, &end, &b->point2);
635 /* It can be shown that if the control points of a cubic Bézier curve lie
636 * on the same side of the line through the endpoints, the distance of the
637 * curve itself to that line will be within 3/4 of the distance of the
638 * control points to that line; if the control points lie on opposite
639 * sides, that distance will be within 4/9 of the distance of the
640 * corresponding control point. We're taking that as a given here. */
641 if (d1 * d2 > 0.0f)
642 {
643 d1 *= 0.75f;
644 d2 *= 0.75f;
645 }
646 else
647 {
648 d1 = (d1 * 4.0f) / 9.0f;
649 d2 = (d2 * 4.0f) / 9.0f;
650 }
651 w2 = max(fabsf(d1), fabsf(d2));
652
653 /* Project the control points onto the line through the endpoints of the
654 * curve. We will use these to calculate the endpoints of the
655 * approximation. */
656 d2d_point_subtract(&t[1], &b->point1, p0);
657 d1 = d2d_point_dot(&v_p, &t[1]);
658 d2d_point_subtract(&t[2], &b->point2, p0);
659 d2 = d2d_point_dot(&v_p, &t[2]);
660
661 /* Calculate the start point of the approximation. Like further above, the
662 * actual curve is somewhat closer to the endpoints than the control
663 * points are. */
664 d = min(min(d1, d2), 0);
665 if (d1 * d2 > 0.0f)
666 d *= 0.75f;
667 else
668 d = (d * 4.0f) / 9.0f;
669 /* Account for the stroke width and tolerance around the endpoints by
670 * adjusting the endpoints here. This matters because there are no joins
671 * in the original geometry for the places where we subdivide the original
672 * curve. We do this here because it's easy; alternatively we could
673 * explicitly test for this when subdividing the curve further below. */
674 d -= min(w + tolerance, w2);
675 start.x = p0->x + d * v_p.x;
676 start.y = p0->y + d * v_p.y;
677
678 /* Calculate the end point of the approximation. */
679 d1 -= m;
680 d2 -= m;
681 d = max(max(d1, d2), 0);
682 if (d1 * d2 > 0.0f)
683 d = m + d * 0.75f;
684 else
685 d = m + (d * 4.0f) / 9.0f;
686 d += min(w2, w + tolerance);
687 end.x = p0->x + d * v_p.x;
688 end.y = p0->y + d * v_p.y;
689
690 /* Calculate the error bounds of the approximation. We do this in
691 * transformed space because we need these to be relative to the given
692 * tolerance. */
693
694 d2d_point_transform(&t[0], transform, p0->x, p0->y);
695 d2d_point_transform(&t[1], transform, b->point1.x, b->point1.y);
696 d2d_point_transform(&t[2], transform, b->point2.x, b->point2.y);
697 d2d_point_transform(&t[3], transform, b->point3.x, b->point3.y);
700
701 d2d_point_subtract(&t[6], &t[5], &t[4]);
702 l = d2d_point_length(&t[6]);
703 /* Here, d1 and d2 are the maximum (signed) distance of the control points
704 * from the line through the start and end points. */
705 d1 = d2d_point_ccw(&t[4], &t[5], &t[1]) / l;
706 d2 = d2d_point_ccw(&t[4], &t[5], &t[2]) / l;
707 if (d1 * d2 > 0.0f)
708 {
709 d1 *= 0.75f;
710 d2 *= 0.75f;
711 }
712 else
713 {
714 d1 = (d1 * 4.0f) / 9.0f;
715 d2 = (d2 * 4.0f) / 9.0f;
716 }
717 l = max(max(d1, d2), 0) - min(min(d1, d2), 0);
718
719 /* d3 and d4 are the (unsigned) distance of the endpoints of the
720 * approximation from the original endpoints. */
721 d2d_point_subtract(&t[6], &t[4], &t[0]);
722 d3 = d2d_point_length(&t[6]);
723 d2d_point_subtract(&t[6], &t[5], &t[3]);
724 d4 = d2d_point_length(&t[6]);
725 l = max(max(d3, d4), l);
726
727 /* If the error of the approximation is less than the tolerance, and Q
728 * lies on the approximation, the distance of Q to the stroked curve is
729 * definitely within the tolerance. */
730 if (l <= tolerance && d2d_point_on_line_segment(q, &start, &end, transform, w, tolerance - l))
731 return TRUE;
732 /* On the other hand, if the distance of Q to the stroked curve is more
733 * than the sum of the tolerance and d, the distance of Q to the stroked
734 * curve can't possibly be within the tolerance. */
735 if (!d2d_point_on_line_segment(q, &start, &end, transform, w + w2, tolerance))
736 return FALSE;
737
738 /* Subdivide the curve. Note that simply splitting the segment in half
739 * here works and is easy, but may not be optimal. We could potentially
740 * reduce the number of iterations we need to do by splitting based on
741 * curvature or segment length. */
742 d2d_point_lerp(&t[0], &b->point1, &b->point2, 0.5f);
743
744 b1.point3 = b->point3;
745 d2d_point_lerp(&b1.point2, &b->point3, &b->point2, 0.5f);
746 d2d_point_lerp(&b1.point1, &t[0], &b1.point2, 0.5f);
747
748 d2d_point_lerp(&b0.point1, p0, &b->point1, 0.5f);
749 d2d_point_lerp(&b0.point2, &t[0], &b0.point1, 0.5f);
750 d2d_point_lerp(&b0.point3, &b0.point2, &b1.point1, 0.5f);
751
752 return d2d_point_on_bezier_segment(q, p0, &b0, transform, stroke_width, tolerance)
753 || d2d_point_on_bezier_segment(q, &b0.point3, &b1, transform, stroke_width, tolerance);
754}
755
757{
758 l->left = min(l->left, r->left);
759 l->top = min(l->top, r->top);
760 l->right = max(l->right, r->right);
761 l->bottom = max(l->bottom, r->bottom);
762}
763
765{
766 return p->left < q->right && p->top < q->bottom && p->right > q->left && p->bottom > q->top;
767}
768
770 const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2)
771{
773 float root;
774
775 bounds->left = p0->x;
776 bounds->top = p0->y;
777 bounds->right = p0->x;
778 bounds->bottom = p0->y;
779
780 d2d_rect_expand(bounds, p2);
781
782 /* f(t) = (1 - t)²P₀ + 2(1 - t)tP₁ + t²P₂
783 * f'(t) = 2(1 - t)(P₁ - P₀) + 2t(P₂ - P₁)
784 * = 2(P₂ - 2P₁ + P₀)t + 2(P₁ - P₀)
785 *
786 * f'(t) = 0
787 * t = (P₀ - P₁) / (P₂ - 2P₁ + P₀) */
788 root = (p0->x - p1->x) / (p2->x - 2.0f * p1->x + p0->x);
789 if (root > 0.0f && root < 1.0f)
790 {
791 d2d_point_calculate_bezier(&p, p0, p1, p2, root);
792 d2d_rect_expand(bounds, &p);
793 }
794
795 root = (p0->y - p1->y) / (p2->y - 2.0f * p1->y + p0->y);
796 if (root > 0.0f && root < 1.0f)
797 {
798 d2d_point_calculate_bezier(&p, p0, p1, p2, root);
799 d2d_rect_expand(bounds, &p);
800 }
801}
802
804 const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2, float start, float end)
805{
806 D2D1_POINT_2F q[3], r[2];
807
808 d2d_point_lerp(&r[0], p0, p1, start);
809 d2d_point_lerp(&r[1], p1, p2, start);
810 d2d_point_lerp(&q[0], &r[0], &r[1], start);
811
812 end = (end - start) / (1.0f - start);
813 d2d_point_lerp(&q[1], &q[0], &r[1], end);
814 d2d_point_lerp(&r[0], &r[1], p2, end);
815 d2d_point_lerp(&q[2], &q[1], &r[0], end);
816
817 d2d_rect_get_bezier_bounds(bounds, &q[0], &q[1], &q[2]);
818}
819
821{
822 if (!d2d_array_reserve((void **)&figure->vertices, &figure->vertices_size,
823 figure->vertex_count + 1, sizeof(*figure->vertices)))
824 {
825 ERR("Failed to grow vertices array.\n");
826 return FALSE;
827 }
828
829 if (!d2d_array_reserve((void **)&figure->vertex_types, &figure->vertex_types_size,
830 figure->vertex_count + 1, sizeof(*figure->vertex_types)))
831 {
832 ERR("Failed to grow vertex types array.\n");
833 return FALSE;
834 }
835
836 memmove(&figure->vertices[idx + 1], &figure->vertices[idx],
837 (figure->vertex_count - idx) * sizeof(*figure->vertices));
838 memmove(&figure->vertex_types[idx + 1], &figure->vertex_types[idx],
839 (figure->vertex_count - idx) * sizeof(*figure->vertex_types));
840 figure->vertices[idx] = vertex;
842 d2d_rect_expand(&figure->bounds, &vertex);
843 ++figure->vertex_count;
844 return TRUE;
845}
846
848{
849 size_t last = figure->vertex_count - 1;
850
851 if (figure->vertex_count && figure->vertex_types[last] == D2D_VERTEX_TYPE_LINE
852 && !memcmp(&figure->vertices[last], &vertex, sizeof(vertex)))
853 return TRUE;
854
855 if (!d2d_array_reserve((void **)&figure->vertices, &figure->vertices_size,
856 figure->vertex_count + 1, sizeof(*figure->vertices)))
857 {
858 ERR("Failed to grow vertices array.\n");
859 return FALSE;
860 }
861
862 if (!d2d_array_reserve((void **)&figure->vertex_types, &figure->vertex_types_size,
863 figure->vertex_count + 1, sizeof(*figure->vertex_types)))
864 {
865 ERR("Failed to grow vertex types array.\n");
866 return FALSE;
867 }
868
869 figure->vertices[figure->vertex_count] = vertex;
871 d2d_rect_expand(&figure->bounds, &vertex);
872 ++figure->vertex_count;
873 return TRUE;
874}
875
877 size_t idx, size_t count, const D2D1_POINT_2F *p)
878{
879 if (!d2d_array_reserve((void **)&figure->bezier_controls, &figure->bezier_controls_size,
880 figure->bezier_control_count + count, sizeof(*figure->bezier_controls)))
881 {
882 ERR("Failed to grow bezier controls array.\n");
883 return FALSE;
884 }
885
886 memmove(&figure->bezier_controls[idx + count], &figure->bezier_controls[idx],
887 (figure->bezier_control_count - idx) * sizeof(*figure->bezier_controls));
888 memcpy(&figure->bezier_controls[idx], p, count * sizeof(*figure->bezier_controls));
889 figure->bezier_control_count += count;
890
891 return TRUE;
892}
893
895{
896 if (!d2d_array_reserve((void **)&figure->bezier_controls, &figure->bezier_controls_size,
897 figure->bezier_control_count + count, sizeof(*figure->bezier_controls)))
898 {
899 ERR("Failed to grow bezier controls array.\n");
900 return FALSE;
901 }
902
903 memcpy(&figure->bezier_controls[figure->bezier_control_count], p, count * sizeof(*figure->bezier_controls));
904 figure->bezier_control_count += count;
905
906 return TRUE;
907}
908
910{
913 {
914 ERR("Failed to grow cubic Bézier controls array.\n");
915 return FALSE;
916 }
917
919 p, count * sizeof(*figure->original_bezier_controls));
921
922 return TRUE;
923}
924
925static void d2d_cdt_edge_rot(struct d2d_cdt_edge_ref *dst, const struct d2d_cdt_edge_ref *src)
926{
927 dst->idx = src->idx;
928 dst->r = (src->r + D2D_EDGE_NEXT_ROT) & 3;
929}
930
931static void d2d_cdt_edge_sym(struct d2d_cdt_edge_ref *dst, const struct d2d_cdt_edge_ref *src)
932{
933 dst->idx = src->idx;
934 dst->r = (src->r + D2D_EDGE_NEXT_SYM) & 3;
935}
936
937static void d2d_cdt_edge_tor(struct d2d_cdt_edge_ref *dst, const struct d2d_cdt_edge_ref *src)
938{
939 dst->idx = src->idx;
940 dst->r = (src->r + D2D_EDGE_NEXT_TOR) & 3;
941}
942
943static void d2d_cdt_edge_next_left(const struct d2d_cdt *cdt,
944 struct d2d_cdt_edge_ref *dst, const struct d2d_cdt_edge_ref *src)
945{
946 d2d_cdt_edge_rot(dst, &cdt->edges[src->idx].next[(src->r + D2D_EDGE_NEXT_TOR) & 3]);
947}
948
949static void d2d_cdt_edge_next_origin(const struct d2d_cdt *cdt,
950 struct d2d_cdt_edge_ref *dst, const struct d2d_cdt_edge_ref *src)
951{
952 *dst = cdt->edges[src->idx].next[src->r];
953}
954
955static void d2d_cdt_edge_prev_origin(const struct d2d_cdt *cdt,
956 struct d2d_cdt_edge_ref *dst, const struct d2d_cdt_edge_ref *src)
957{
958 d2d_cdt_edge_rot(dst, &cdt->edges[src->idx].next[(src->r + D2D_EDGE_NEXT_ROT) & 3]);
959}
960
961static size_t d2d_cdt_edge_origin(const struct d2d_cdt *cdt, const struct d2d_cdt_edge_ref *e)
962{
963 return cdt->edges[e->idx].vertex[e->r >> 1];
964}
965
966static size_t d2d_cdt_edge_destination(const struct d2d_cdt *cdt, const struct d2d_cdt_edge_ref *e)
967{
968 return cdt->edges[e->idx].vertex[!(e->r >> 1)];
969}
970
971static void d2d_cdt_edge_set_origin(const struct d2d_cdt *cdt,
972 const struct d2d_cdt_edge_ref *e, size_t vertex)
973{
974 cdt->edges[e->idx].vertex[e->r >> 1] = vertex;
975}
976
977static void d2d_cdt_edge_set_destination(const struct d2d_cdt *cdt,
978 const struct d2d_cdt_edge_ref *e, size_t vertex)
979{
980 cdt->edges[e->idx].vertex[!(e->r >> 1)] = vertex;
981}
982
983static float d2d_cdt_ccw(const struct d2d_cdt *cdt, size_t a, size_t b, size_t c)
984{
985 return d2d_point_ccw(&cdt->vertices[a], &cdt->vertices[b], &cdt->vertices[c]);
986}
987
988static BOOL d2d_cdt_rightof(const struct d2d_cdt *cdt, size_t p, const struct d2d_cdt_edge_ref *e)
989{
990 return d2d_cdt_ccw(cdt, p, d2d_cdt_edge_destination(cdt, e), d2d_cdt_edge_origin(cdt, e)) > 0.0f;
991}
992
993static BOOL d2d_cdt_leftof(const struct d2d_cdt *cdt, size_t p, const struct d2d_cdt_edge_ref *e)
994{
995 return d2d_cdt_ccw(cdt, p, d2d_cdt_edge_origin(cdt, e), d2d_cdt_edge_destination(cdt, e)) > 0.0f;
996}
997
998/* |ax ay|
999 * |bx by| */
1000static void d2d_fp_four_det2x2(float *out, float ax, float ay, float bx, float by)
1001{
1002 float axby[2], aybx[2];
1003
1004 d2d_fp_two_product(axby, ax, by);
1005 d2d_fp_two_product(aybx, ay, bx);
1006 d2d_fp_two_two_diff(out, axby, aybx);
1007}
1008
1009/* (a->x² + a->y²) * det2x2 */
1010static void d2d_fp_sub_det3x3(float *out, size_t *out_len, const struct d2d_fp_two_vec2 *a, const float *det2x2)
1011{
1012 size_t axd_len, ayd_len, axxd_len, ayyd_len;
1013 float axd[8], ayd[8], axxd[16], ayyd[16];
1014
1015 d2d_fp_scale_expansion_zeroelim(axd, &axd_len, det2x2, 4, a->x[1]);
1016 d2d_fp_scale_expansion_zeroelim(axxd, &axxd_len, axd, axd_len, a->x[1]);
1017 d2d_fp_scale_expansion_zeroelim(ayd, &ayd_len, det2x2, 4, a->y[1]);
1018 d2d_fp_scale_expansion_zeroelim(ayyd, &ayyd_len, ayd, ayd_len, a->y[1]);
1019 d2d_fp_fast_expansion_sum_zeroelim(out, out_len, axxd, axxd_len, ayyd, ayyd_len);
1020}
1021
1022/* det_abt = det_ab * c[0]
1023 * fin += c[0] * (az * b - bz * a + c[1] * det_ab * 2.0f) */
1024static void d2d_cdt_incircle_refine1(struct d2d_fp_fin *fin, float *det_abt, size_t *det_abt_len,
1025 const float *det_ab, float a, const float *az, float b, const float *bz, const float *c)
1026{
1027 size_t temp48_len, temp32_len, temp16a_len, temp16b_len, temp16c_len, temp8_len;
1028 float temp48[48], temp32[32], temp16a[16], temp16b[16], temp16c[16], temp8[8];
1029 float *swap;
1030
1031 d2d_fp_scale_expansion_zeroelim(det_abt, det_abt_len, det_ab, 4, c[0]);
1032 d2d_fp_scale_expansion_zeroelim(temp16a, &temp16a_len, det_abt, *det_abt_len, 2.0f * c[1]);
1033 d2d_fp_scale_expansion_zeroelim(temp8, &temp8_len, az, 4, c[0]);
1034 d2d_fp_scale_expansion_zeroelim(temp16b, &temp16b_len, temp8, temp8_len, b);
1035 d2d_fp_scale_expansion_zeroelim(temp8, &temp8_len, bz, 4, c[0]);
1036 d2d_fp_scale_expansion_zeroelim(temp16c, &temp16c_len, temp8, temp8_len, -a);
1037 d2d_fp_fast_expansion_sum_zeroelim(temp32, &temp32_len, temp16a, temp16a_len, temp16b, temp16b_len);
1038 d2d_fp_fast_expansion_sum_zeroelim(temp48, &temp48_len, temp16c, temp16c_len, temp32, temp32_len);
1039 d2d_fp_fast_expansion_sum_zeroelim(fin->other, &fin->length, fin->now, fin->length, temp48, temp48_len);
1040 swap = fin->now; fin->now = fin->other; fin->other = swap;
1041}
1042
1043static void d2d_cdt_incircle_refine2(struct d2d_fp_fin *fin, const struct d2d_fp_two_vec2 *a,
1044 const struct d2d_fp_two_vec2 *b, const float *bz, const struct d2d_fp_two_vec2 *c, const float *cz,
1045 const float *axt_det_bc, size_t axt_det_bc_len, const float *ayt_det_bc, size_t ayt_det_bc_len)
1046{
1047 size_t temp64_len, temp48_len, temp32a_len, temp32b_len, temp16a_len, temp16b_len, temp8_len;
1048 float temp64[64], temp48[48], temp32a[32], temp32b[32], temp16a[16], temp16b[16], temp8[8];
1049 float bct[8], bctt[4], temp4a[4], temp4b[4], temp2a[2], temp2b[2];
1050 size_t bct_len, bctt_len;
1051 float *swap;
1052
1053 /* bct = (b->x[0] * c->y[1] + b->x[1] * c->y[0]) - (c->x[0] * b->y[1] + c->x[1] * b->y[0]) */
1054 /* bctt = b->x[0] * c->y[0] + c->x[0] * b->y[0] */
1055 if (b->x[0] != 0.0f || b->y[0] != 0.0f || c->x[0] != 0.0f || c->y[0] != 0.0f)
1056 {
1057 d2d_fp_two_product(temp2a, b->x[0], c->y[1]);
1058 d2d_fp_two_product(temp2b, b->x[1], c->y[0]);
1059 d2d_fp_two_two_sum(temp4a, temp2a, temp2b);
1060 d2d_fp_two_product(temp2a, c->x[0], -b->y[1]);
1061 d2d_fp_two_product(temp2b, c->x[1], -b->y[0]);
1062 d2d_fp_two_two_sum(temp4b, temp2a, temp2b);
1063 d2d_fp_fast_expansion_sum_zeroelim(bct, &bct_len, temp4a, 4, temp4b, 4);
1064
1065 d2d_fp_two_product(temp2a, b->x[0], c->y[0]);
1066 d2d_fp_two_product(temp2b, c->x[0], b->y[0]);
1067 d2d_fp_two_two_diff(bctt, temp2a, temp2b);
1068 bctt_len = 4;
1069 }
1070 else
1071 {
1072 bct[0] = 0.0f;
1073 bct_len = 1;
1074 bctt[0] = 0.0f;
1075 bctt_len = 1;
1076 }
1077
1078 if (a->x[0] != 0.0f)
1079 {
1080 size_t axt_bct_len, axt_bctt_len;
1081 float axt_bct[16], axt_bctt[8];
1082
1083 /* fin += a->x[0] * (axt_det_bc + bct * 2.0f * a->x[1]) */
1084 d2d_fp_scale_expansion_zeroelim(temp16a, &temp16a_len, axt_det_bc, axt_det_bc_len, a->x[0]);
1085 d2d_fp_scale_expansion_zeroelim(axt_bct, &axt_bct_len, bct, bct_len, a->x[0]);
1086 d2d_fp_scale_expansion_zeroelim(temp32a, &temp32a_len, axt_bct, axt_bct_len, 2.0f * a->x[1]);
1087 d2d_fp_fast_expansion_sum_zeroelim(temp48, &temp48_len, temp16a, temp16a_len, temp32a, temp32a_len);
1088 d2d_fp_fast_expansion_sum_zeroelim(fin->other, &fin->length, fin->now, fin->length, temp48, temp48_len);
1089 swap = fin->now; fin->now = fin->other; fin->other = swap;
1090
1091 if (b->y[0] != 0.0f)
1092 {
1093 /* fin += a->x[0] * cz * b->y[0] */
1094 d2d_fp_scale_expansion_zeroelim(temp8, &temp8_len, cz, 4, a->x[0]);
1095 d2d_fp_scale_expansion_zeroelim(temp16a, &temp16a_len, temp8, temp8_len, b->y[0]);
1096 d2d_fp_fast_expansion_sum_zeroelim(fin->other, &fin->length, fin->now, fin->length, temp16a, temp16a_len);
1097 swap = fin->now; fin->now = fin->other; fin->other = swap;
1098 }
1099
1100 if (c->y[0] != 0.0f)
1101 {
1102 /* fin -= a->x[0] * bz * c->y[0] */
1103 d2d_fp_scale_expansion_zeroelim(temp8, &temp8_len, bz, 4, -a->x[0]);
1104 d2d_fp_scale_expansion_zeroelim(temp16a, &temp16a_len, temp8, temp8_len, c->y[0]);
1105 d2d_fp_fast_expansion_sum_zeroelim(fin->other, &fin->length, fin->now, fin->length, temp16a, temp16a_len);
1106 swap = fin->now; fin->now = fin->other; fin->other = swap;
1107 }
1108
1109 /* fin += a->x[0] * (bct * a->x[0] + bctt * (2.0f * a->x[1] + a->x[0])) */
1110 d2d_fp_scale_expansion_zeroelim(temp32a, &temp32a_len, axt_bct, axt_bct_len, a->x[0]);
1111 d2d_fp_scale_expansion_zeroelim(axt_bctt, &axt_bctt_len, bctt, bctt_len, a->x[0]);
1112 d2d_fp_scale_expansion_zeroelim(temp16a, &temp16a_len, axt_bctt, axt_bctt_len, 2.0f * a->x[1]);
1113 d2d_fp_scale_expansion_zeroelim(temp16b, &temp16b_len, axt_bctt, axt_bctt_len, a->x[0]);
1114 d2d_fp_fast_expansion_sum_zeroelim(temp32b, &temp32b_len, temp16a, temp16a_len, temp16b, temp16b_len);
1115 d2d_fp_fast_expansion_sum_zeroelim(temp64, &temp64_len, temp32a, temp32a_len, temp32b, temp32b_len);
1116 d2d_fp_fast_expansion_sum_zeroelim(fin->other, &fin->length, fin->now, fin->length, temp64, temp64_len);
1117 swap = fin->now; fin->now = fin->other; fin->other = swap;
1118 }
1119
1120 if (a->y[0] != 0.0f)
1121 {
1122 size_t ayt_bct_len, ayt_bctt_len;
1123 float ayt_bct[16], ayt_bctt[8];
1124
1125 /* fin += a->y[0] * (ayt_det_bc + bct * 2.0f * a->y[1]) */
1126 d2d_fp_scale_expansion_zeroelim(temp16a, &temp16a_len, ayt_det_bc, ayt_det_bc_len, a->y[0]);
1127 d2d_fp_scale_expansion_zeroelim(ayt_bct, &ayt_bct_len, bct, bct_len, a->y[0]);
1128 d2d_fp_scale_expansion_zeroelim(temp32a, &temp32a_len, ayt_bct, ayt_bct_len, 2.0f * a->y[1]);
1129 d2d_fp_fast_expansion_sum_zeroelim(temp48, &temp48_len, temp16a, temp16a_len, temp32a, temp32a_len);
1130 d2d_fp_fast_expansion_sum_zeroelim(fin->other, &fin->length, fin->now, fin->length, temp48, temp48_len);
1131 swap = fin->now; fin->now = fin->other; fin->other = swap;
1132
1133 /* fin += a->y[0] * (bct * a->y[0] + bctt * (2.0f * a->y[1] + a->y[0])) */
1134 d2d_fp_scale_expansion_zeroelim(temp32a, &temp32a_len, ayt_bct, ayt_bct_len, a->y[0]);
1135 d2d_fp_scale_expansion_zeroelim(ayt_bctt, &ayt_bctt_len, bctt, bctt_len, a->y[0]);
1136 d2d_fp_scale_expansion_zeroelim(temp16a, &temp16a_len, ayt_bctt, ayt_bctt_len, 2.0f * a->y[1]);
1137 d2d_fp_scale_expansion_zeroelim(temp16b, &temp16b_len, ayt_bctt, ayt_bctt_len, a->y[0]);
1138 d2d_fp_fast_expansion_sum_zeroelim(temp32b, &temp32b_len, temp16a, temp16a_len, temp16b, temp16b_len);
1139 d2d_fp_fast_expansion_sum_zeroelim(temp64, &temp64_len, temp32a, temp32a_len, temp32b, temp32b_len);
1140 d2d_fp_fast_expansion_sum_zeroelim(fin->other, &fin->length, fin->now, fin->length, temp64, temp64_len);
1141 swap = fin->now; fin->now = fin->other; fin->other = swap;
1142 }
1143}
1144
1145/* Determine if point D is inside or outside the circle defined by points A,
1146 * B, C. As explained in the paper by Guibas and Stolfi, this is equivalent to
1147 * calculating the signed volume of the tetrahedron defined by projecting the
1148 * points onto the paraboloid of revolution x = x² + y²,
1149 * λ:(x, y) → (x, y, x² + y²). I.e., D is inside the cirlce if
1150 *
1151 * |λ(A) 1|
1152 * |λ(B) 1| > 0
1153 * |λ(C) 1|
1154 * |λ(D) 1|
1155 *
1156 * After translating D to the origin, that becomes:
1157 *
1158 * |λ(A-D)|
1159 * |λ(B-D)| > 0
1160 * |λ(C-D)|
1161 *
1162 * This implementation is based on the paper "Adaptive Precision
1163 * Floating-Point Arithmetic and Fast Robust Geometric Predicates" and
1164 * associated (Public Domain) code by Jonathan Richard Shewchuk. */
1165static BOOL d2d_cdt_incircle(const struct d2d_cdt *cdt, size_t a, size_t b, size_t c, size_t d)
1166{
1167 static const float err_bound_result = (3.0f + 8.0f * D2D_FP_EPS) * D2D_FP_EPS;
1168 static const float err_bound_a = (10.0f + 96.0f * D2D_FP_EPS) * D2D_FP_EPS;
1169 static const float err_bound_b = (4.0f + 48.0f * D2D_FP_EPS) * D2D_FP_EPS;
1170 static const float err_bound_c = (44.0f + 576.0f * D2D_FP_EPS) * D2D_FP_EPS * D2D_FP_EPS;
1171
1172 size_t axt_det_bc_len, ayt_det_bc_len, bxt_det_ca_len, byt_det_ca_len, cxt_det_ab_len, cyt_det_ab_len;
1173 float axt_det_bc[8], ayt_det_bc[8], bxt_det_ca[8], byt_det_ca[8], cxt_det_ab[8], cyt_det_ab[8];
1174 float fin1[1152], fin2[1152], temp64[64], sub_det_a[32], sub_det_b[32], sub_det_c[32];
1175 float det_bc[4], det_ca[4], det_ab[4], daz[4], dbz[4], dcz[4], temp2a[2], temp2b[2];
1176 size_t temp64_len, sub_det_a_len, sub_det_b_len, sub_det_c_len;
1177 float dbxdcy, dbydcx, dcxday, dcydax, daxdby, daydbx;
1178 const D2D1_POINT_2F *p = cdt->vertices;
1179 struct d2d_fp_two_vec2 da, db, dc;
1180 float permanent, err_bound, det;
1181 struct d2d_fp_fin fin;
1182
1183 da.x[1] = p[a].x - p[d].x;
1184 da.y[1] = p[a].y - p[d].y;
1185 db.x[1] = p[b].x - p[d].x;
1186 db.y[1] = p[b].y - p[d].y;
1187 dc.x[1] = p[c].x - p[d].x;
1188 dc.y[1] = p[c].y - p[d].y;
1189
1190 daz[3] = da.x[1] * da.x[1] + da.y[1] * da.y[1];
1191 dbxdcy = db.x[1] * dc.y[1];
1192 dbydcx = db.y[1] * dc.x[1];
1193
1194 dbz[3] = db.x[1] * db.x[1] + db.y[1] * db.y[1];
1195 dcxday = dc.x[1] * da.y[1];
1196 dcydax = dc.y[1] * da.x[1];
1197
1198 dcz[3] = dc.x[1] * dc.x[1] + dc.y[1] * dc.y[1];
1199 daxdby = da.x[1] * db.y[1];
1200 daydbx = da.y[1] * db.x[1];
1201
1202 det = daz[3] * (dbxdcy - dbydcx) + dbz[3] * (dcxday - dcydax) + dcz[3] * (daxdby - daydbx);
1203 permanent = daz[3] * (fabsf(dbxdcy) + fabsf(dbydcx))
1204 + dbz[3] * (fabsf(dcxday) + fabsf(dcydax))
1205 + dcz[3] * (fabsf(daxdby) + fabsf(daydbx));
1206 err_bound = err_bound_a * permanent;
1207 if (det > err_bound || -det > err_bound)
1208 return det > 0.0f;
1209
1210 fin.now = fin1;
1211 fin.other = fin2;
1212
1213 d2d_fp_four_det2x2(det_bc, db.x[1], db.y[1], dc.x[1], dc.y[1]);
1214 d2d_fp_sub_det3x3(sub_det_a, &sub_det_a_len, &da, det_bc);
1215
1216 d2d_fp_four_det2x2(det_ca, dc.x[1], dc.y[1], da.x[1], da.y[1]);
1217 d2d_fp_sub_det3x3(sub_det_b, &sub_det_b_len, &db, det_ca);
1218
1219 d2d_fp_four_det2x2(det_ab, da.x[1], da.y[1], db.x[1], db.y[1]);
1220 d2d_fp_sub_det3x3(sub_det_c, &sub_det_c_len, &dc, det_ab);
1221
1222 d2d_fp_fast_expansion_sum_zeroelim(temp64, &temp64_len, sub_det_a, sub_det_a_len, sub_det_b, sub_det_b_len);
1223 d2d_fp_fast_expansion_sum_zeroelim(fin.now, &fin.length, temp64, temp64_len, sub_det_c, sub_det_c_len);
1224 det = d2d_fp_estimate(fin.now, fin.length);
1225 err_bound = err_bound_b * permanent;
1226 if (det >= err_bound || -det >= err_bound)
1227 return det > 0.0f;
1228
1229 d2d_fp_two_diff_tail(&da.x[0], p[a].x, p[d].x, da.x[1]);
1230 d2d_fp_two_diff_tail(&da.y[0], p[a].y, p[d].y, da.y[1]);
1231 d2d_fp_two_diff_tail(&db.x[0], p[b].x, p[d].x, db.x[1]);
1232 d2d_fp_two_diff_tail(&db.y[0], p[b].y, p[d].y, db.y[1]);
1233 d2d_fp_two_diff_tail(&dc.x[0], p[c].x, p[d].x, dc.x[1]);
1234 d2d_fp_two_diff_tail(&dc.y[0], p[c].y, p[d].y, dc.y[1]);
1235 if (da.x[0] == 0.0f && db.x[0] == 0.0f && dc.x[0] == 0.0f
1236 && da.y[0] == 0.0f && db.y[0] == 0.0f && dc.y[0] == 0.0f)
1237 return det > 0.0f;
1238
1239 err_bound = err_bound_c * permanent + err_bound_result * fabsf(det);
1240 det += (daz[3] * ((db.x[1] * dc.y[0] + dc.y[1] * db.x[0]) - (db.y[1] * dc.x[0] + dc.x[1] * db.y[0]))
1241 + 2.0f * (da.x[1] * da.x[0] + da.y[1] * da.y[0]) * (db.x[1] * dc.y[1] - db.y[1] * dc.x[1]))
1242 + (dbz[3] * ((dc.x[1] * da.y[0] + da.y[1] * dc.x[0]) - (dc.y[1] * da.x[0] + da.x[1] * dc.y[0]))
1243 + 2.0f * (db.x[1] * db.x[0] + db.y[1] * db.y[0]) * (dc.x[1] * da.y[1] - dc.y[1] * da.x[1]))
1244 + (dcz[3] * ((da.x[1] * db.y[0] + db.y[1] * da.x[0]) - (da.y[1] * db.x[0] + db.x[1] * da.y[0]))
1245 + 2.0f * (dc.x[1] * dc.x[0] + dc.y[1] * dc.y[0]) * (da.x[1] * db.y[1] - da.y[1] * db.x[1]));
1246 if (det >= err_bound || -det >= err_bound)
1247 return det > 0.0f;
1248
1249 if (db.x[0] != 0.0f || db.y[0] != 0.0f || dc.x[0] != 0.0f || dc.y[0] != 0.0f)
1250 {
1251 d2d_fp_square(temp2a, da.x[1]);
1252 d2d_fp_square(temp2b, da.y[1]);
1253 d2d_fp_two_two_sum(daz, temp2a, temp2b);
1254 }
1255 if (dc.x[0] != 0.0f || dc.y[0] != 0.0f || da.x[0] != 0.0f || da.y[0] != 0.0f)
1256 {
1257 d2d_fp_square(temp2a, db.x[1]);
1258 d2d_fp_square(temp2b, db.y[1]);
1259 d2d_fp_two_two_sum(dbz, temp2a, temp2b);
1260 }
1261 if (da.x[0] != 0.0f || da.y[0] != 0.0f || db.x[0] != 0.0f || db.y[0] != 0.0f)
1262 {
1263 d2d_fp_square(temp2a, dc.x[1]);
1264 d2d_fp_square(temp2b, dc.y[1]);
1265 d2d_fp_two_two_sum(dcz, temp2a, temp2b);
1266 }
1267
1268 if (da.x[0] != 0.0f)
1269 d2d_cdt_incircle_refine1(&fin, axt_det_bc, &axt_det_bc_len, det_bc, dc.y[1], dcz, db.y[1], dbz, da.x);
1270 if (da.y[0] != 0.0f)
1271 d2d_cdt_incircle_refine1(&fin, ayt_det_bc, &ayt_det_bc_len, det_bc, db.x[1], dbz, dc.x[1], dcz, da.y);
1272 if (db.x[0] != 0.0f)
1273 d2d_cdt_incircle_refine1(&fin, bxt_det_ca, &bxt_det_ca_len, det_ca, da.y[1], daz, dc.y[1], dcz, db.x);
1274 if (db.y[0] != 0.0f)
1275 d2d_cdt_incircle_refine1(&fin, byt_det_ca, &byt_det_ca_len, det_ca, dc.x[1], dcz, da.x[1], daz, db.y);
1276 if (dc.x[0] != 0.0f)
1277 d2d_cdt_incircle_refine1(&fin, cxt_det_ab, &cxt_det_ab_len, det_ab, db.y[1], dbz, da.y[1], daz, dc.x);
1278 if (dc.y[0] != 0.0f)
1279 d2d_cdt_incircle_refine1(&fin, cyt_det_ab, &cyt_det_ab_len, det_ab, da.x[1], daz, db.x[1], dbz, dc.y);
1280
1281 if (da.x[0] != 0.0f || da.y[0] != 0.0f)
1282 d2d_cdt_incircle_refine2(&fin, &da, &db, dbz, &dc, dcz,
1283 axt_det_bc, axt_det_bc_len, ayt_det_bc, ayt_det_bc_len);
1284 if (db.x[0] != 0.0f || db.y[0] != 0.0f)
1285 d2d_cdt_incircle_refine2(&fin, &db, &dc, dcz, &da, daz,
1286 bxt_det_ca, bxt_det_ca_len, byt_det_ca, byt_det_ca_len);
1287 if (dc.x[0] != 0.0f || dc.y[0] != 0.0f)
1288 d2d_cdt_incircle_refine2(&fin, &dc, &da, daz, &db, dbz,
1289 cxt_det_ab, cxt_det_ab_len, cyt_det_ab, cyt_det_ab_len);
1290
1291 return fin.now[fin.length - 1] > 0.0f;
1292}
1293
1294static void d2d_cdt_splice(const struct d2d_cdt *cdt, const struct d2d_cdt_edge_ref *a,
1295 const struct d2d_cdt_edge_ref *b)
1296{
1297 struct d2d_cdt_edge_ref ta, tb, alpha, beta;
1298
1299 ta = cdt->edges[a->idx].next[a->r];
1300 tb = cdt->edges[b->idx].next[b->r];
1301 cdt->edges[a->idx].next[a->r] = tb;
1302 cdt->edges[b->idx].next[b->r] = ta;
1303
1304 d2d_cdt_edge_rot(&alpha, &ta);
1305 d2d_cdt_edge_rot(&beta, &tb);
1306
1307 ta = cdt->edges[alpha.idx].next[alpha.r];
1308 tb = cdt->edges[beta.idx].next[beta.r];
1309 cdt->edges[alpha.idx].next[alpha.r] = tb;
1310 cdt->edges[beta.idx].next[beta.r] = ta;
1311}
1312
1314{
1315 struct d2d_cdt_edge *edge;
1316
1317 if (cdt->free_edge != ~0u)
1318 {
1319 e->idx = cdt->free_edge;
1320 cdt->free_edge = cdt->edges[e->idx].next[D2D_EDGE_NEXT_ORIGIN].idx;
1321 }
1322 else
1323 {
1324 if (!d2d_array_reserve((void **)&cdt->edges, &cdt->edges_size, cdt->edge_count + 1, sizeof(*cdt->edges)))
1325 {
1326 ERR("Failed to grow edges array.\n");
1327 return FALSE;
1328 }
1329 e->idx = cdt->edge_count++;
1330 }
1331 e->r = 0;
1332
1333 edge = &cdt->edges[e->idx];
1334 edge->next[D2D_EDGE_NEXT_ORIGIN] = *e;
1338 edge->flags = 0;
1339
1340 return TRUE;
1341}
1342
1343static void d2d_cdt_destroy_edge(struct d2d_cdt *cdt, const struct d2d_cdt_edge_ref *e)
1344{
1345 struct d2d_cdt_edge_ref next, sym, prev;
1346
1348 if (next.idx != e->idx || next.r != e->r)
1349 {
1350 d2d_cdt_edge_prev_origin(cdt, &prev, e);
1351 d2d_cdt_splice(cdt, e, &prev);
1352 }
1353
1354 d2d_cdt_edge_sym(&sym, e);
1355
1356 d2d_cdt_edge_next_origin(cdt, &next, &sym);
1357 if (next.idx != sym.idx || next.r != sym.r)
1358 {
1359 d2d_cdt_edge_prev_origin(cdt, &prev, &sym);
1360 d2d_cdt_splice(cdt, &sym, &prev);
1361 }
1362
1363 cdt->edges[e->idx].flags |= D2D_CDT_EDGE_FLAG_FREED;
1364 cdt->edges[e->idx].next[D2D_EDGE_NEXT_ORIGIN].idx = cdt->free_edge;
1365 cdt->free_edge = e->idx;
1366}
1367
1368static BOOL d2d_cdt_connect(struct d2d_cdt *cdt, struct d2d_cdt_edge_ref *e,
1369 const struct d2d_cdt_edge_ref *a, const struct d2d_cdt_edge_ref *b)
1370{
1371 struct d2d_cdt_edge_ref tmp;
1372
1373 if (!d2d_cdt_create_edge(cdt, e))
1374 return FALSE;
1377 d2d_cdt_edge_next_left(cdt, &tmp, a);
1378 d2d_cdt_splice(cdt, e, &tmp);
1379 d2d_cdt_edge_sym(&tmp, e);
1380 d2d_cdt_splice(cdt, &tmp, b);
1381
1382 return TRUE;
1383}
1384
1385static BOOL d2d_cdt_merge(struct d2d_cdt *cdt, struct d2d_cdt_edge_ref *left_outer,
1386 struct d2d_cdt_edge_ref *left_inner, struct d2d_cdt_edge_ref *right_inner,
1387 struct d2d_cdt_edge_ref *right_outer)
1388{
1389 struct d2d_cdt_edge_ref base_edge, tmp;
1390
1391 /* Create the base edge between both parts. */
1392 for (;;)
1393 {
1394 if (d2d_cdt_leftof(cdt, d2d_cdt_edge_origin(cdt, right_inner), left_inner))
1395 {
1396 d2d_cdt_edge_next_left(cdt, left_inner, left_inner);
1397 }
1398 else if (d2d_cdt_rightof(cdt, d2d_cdt_edge_origin(cdt, left_inner), right_inner))
1399 {
1400 d2d_cdt_edge_sym(&tmp, right_inner);
1401 d2d_cdt_edge_next_origin(cdt, right_inner, &tmp);
1402 }
1403 else
1404 {
1405 break;
1406 }
1407 }
1408
1409 d2d_cdt_edge_sym(&tmp, right_inner);
1410 if (!d2d_cdt_connect(cdt, &base_edge, &tmp, left_inner))
1411 return FALSE;
1412 if (d2d_cdt_edge_origin(cdt, left_inner) == d2d_cdt_edge_origin(cdt, left_outer))
1413 d2d_cdt_edge_sym(left_outer, &base_edge);
1414 if (d2d_cdt_edge_origin(cdt, right_inner) == d2d_cdt_edge_origin(cdt, right_outer))
1415 *right_outer = base_edge;
1416
1417 for (;;)
1418 {
1419 struct d2d_cdt_edge_ref left_candidate, right_candidate, sym_base_edge;
1420 BOOL left_valid, right_valid;
1421
1422 /* Find the left candidate. */
1423 d2d_cdt_edge_sym(&sym_base_edge, &base_edge);
1424 d2d_cdt_edge_next_origin(cdt, &left_candidate, &sym_base_edge);
1425 if ((left_valid = d2d_cdt_leftof(cdt, d2d_cdt_edge_destination(cdt, &left_candidate), &sym_base_edge)))
1426 {
1427 d2d_cdt_edge_next_origin(cdt, &tmp, &left_candidate);
1428 while (d2d_cdt_edge_destination(cdt, &tmp) != d2d_cdt_edge_destination(cdt, &sym_base_edge)
1429 && d2d_cdt_incircle(cdt,
1430 d2d_cdt_edge_origin(cdt, &sym_base_edge), d2d_cdt_edge_destination(cdt, &sym_base_edge),
1431 d2d_cdt_edge_destination(cdt, &left_candidate), d2d_cdt_edge_destination(cdt, &tmp)))
1432 {
1433 d2d_cdt_destroy_edge(cdt, &left_candidate);
1434 left_candidate = tmp;
1435 d2d_cdt_edge_next_origin(cdt, &tmp, &left_candidate);
1436 }
1437 }
1438 d2d_cdt_edge_sym(&left_candidate, &left_candidate);
1439
1440 /* Find the right candidate. */
1441 d2d_cdt_edge_prev_origin(cdt, &right_candidate, &base_edge);
1442 if ((right_valid = d2d_cdt_rightof(cdt, d2d_cdt_edge_destination(cdt, &right_candidate), &base_edge)))
1443 {
1444 d2d_cdt_edge_prev_origin(cdt, &tmp, &right_candidate);
1445 while (d2d_cdt_edge_destination(cdt, &tmp) != d2d_cdt_edge_destination(cdt, &base_edge)
1446 && d2d_cdt_incircle(cdt,
1447 d2d_cdt_edge_origin(cdt, &sym_base_edge), d2d_cdt_edge_destination(cdt, &sym_base_edge),
1448 d2d_cdt_edge_destination(cdt, &right_candidate), d2d_cdt_edge_destination(cdt, &tmp)))
1449 {
1450 d2d_cdt_destroy_edge(cdt, &right_candidate);
1451 right_candidate = tmp;
1452 d2d_cdt_edge_prev_origin(cdt, &tmp, &right_candidate);
1453 }
1454 }
1455
1456 if (!left_valid && !right_valid)
1457 break;
1458
1459 /* Connect the appropriate candidate with the base edge. */
1460 if (!left_valid || (right_valid && d2d_cdt_incircle(cdt,
1461 d2d_cdt_edge_origin(cdt, &left_candidate), d2d_cdt_edge_destination(cdt, &left_candidate),
1462 d2d_cdt_edge_origin(cdt, &right_candidate), d2d_cdt_edge_destination(cdt, &right_candidate))))
1463 {
1464 if (!d2d_cdt_connect(cdt, &base_edge, &right_candidate, &sym_base_edge))
1465 return FALSE;
1466 }
1467 else
1468 {
1469 if (!d2d_cdt_connect(cdt, &base_edge, &sym_base_edge, &left_candidate))
1470 return FALSE;
1471 }
1472 }
1473
1474 return TRUE;
1475}
1476
1477/* Create a Delaunay triangulation from a set of vertices. This is an
1478 * implementation of the divide-and-conquer algorithm described by Guibas and
1479 * Stolfi. Should be called with at least two vertices. */
1480static BOOL d2d_cdt_triangulate(struct d2d_cdt *cdt, size_t start_vertex, size_t vertex_count,
1481 struct d2d_cdt_edge_ref *left_edge, struct d2d_cdt_edge_ref *right_edge)
1482{
1483 struct d2d_cdt_edge_ref left_inner, left_outer, right_inner, right_outer, tmp;
1484 size_t cut;
1485
1486 /* Only two vertices, create a single edge. */
1487 if (vertex_count == 2)
1488 {
1489 struct d2d_cdt_edge_ref a;
1490
1491 if (!d2d_cdt_create_edge(cdt, &a))
1492 return FALSE;
1493 d2d_cdt_edge_set_origin(cdt, &a, start_vertex);
1494 d2d_cdt_edge_set_destination(cdt, &a, start_vertex + 1);
1495
1496 *left_edge = a;
1497 d2d_cdt_edge_sym(right_edge, &a);
1498
1499 return TRUE;
1500 }
1501
1502 /* Three vertices, create a triangle. */
1503 if (vertex_count == 3)
1504 {
1505 struct d2d_cdt_edge_ref a, b, c;
1506 float det;
1507
1508 if (!d2d_cdt_create_edge(cdt, &a))
1509 return FALSE;
1510 if (!d2d_cdt_create_edge(cdt, &b))
1511 return FALSE;
1512 d2d_cdt_edge_sym(&tmp, &a);
1513 d2d_cdt_splice(cdt, &tmp, &b);
1514
1515 d2d_cdt_edge_set_origin(cdt, &a, start_vertex);
1516 d2d_cdt_edge_set_destination(cdt, &a, start_vertex + 1);
1517 d2d_cdt_edge_set_origin(cdt, &b, start_vertex + 1);
1518 d2d_cdt_edge_set_destination(cdt, &b, start_vertex + 2);
1519
1520 det = d2d_cdt_ccw(cdt, start_vertex, start_vertex + 1, start_vertex + 2);
1521 if (det != 0.0f && !d2d_cdt_connect(cdt, &c, &b, &a))
1522 return FALSE;
1523
1524 if (det < 0.0f)
1525 {
1526 d2d_cdt_edge_sym(left_edge, &c);
1527 *right_edge = c;
1528 }
1529 else
1530 {
1531 *left_edge = a;
1532 d2d_cdt_edge_sym(right_edge, &b);
1533 }
1534
1535 return TRUE;
1536 }
1537
1538 /* More than three vertices, divide. */
1539 cut = vertex_count / 2;
1540 if (!d2d_cdt_triangulate(cdt, start_vertex, cut, &left_outer, &left_inner))
1541 return FALSE;
1542 if (!d2d_cdt_triangulate(cdt, start_vertex + cut, vertex_count - cut, &right_inner, &right_outer))
1543 return FALSE;
1544 /* Merge the left and right parts. */
1545 if (!d2d_cdt_merge(cdt, &left_outer, &left_inner, &right_inner, &right_outer))
1546 return FALSE;
1547
1548 *left_edge = left_outer;
1549 *right_edge = right_outer;
1550 return TRUE;
1551}
1552
1553static int __cdecl d2d_cdt_compare_vertices(const void *a, const void *b)
1554{
1555 const D2D1_POINT_2F *p0 = a;
1556 const D2D1_POINT_2F *p1 = b;
1557 float diff = p0->x - p1->x;
1558
1559 if (diff == 0.0f)
1560 diff = p0->y - p1->y;
1561
1562 return diff == 0.0f ? 0 : (diff > 0.0f ? 1 : -1);
1563}
1564
1565/* Determine whether a given point is inside the geometry, using the current
1566 * fill mode rule. */
1568 const D2D1_POINT_2F *probe, BOOL triangles_only)
1569{
1570 const D2D1_POINT_2F *p0, *p1;
1571 D2D1_POINT_2F v_p, v_probe;
1572 unsigned int score;
1573 size_t i, j, last;
1574
1575 for (i = 0, score = 0; i < geometry->u.path.figure_count; ++i)
1576 {
1577 const struct d2d_figure *figure = &geometry->u.path.figures[i];
1578
1579 if (probe->x < figure->bounds.left || probe->x > figure->bounds.right
1580 || probe->y < figure->bounds.top || probe->y > figure->bounds.bottom)
1581 continue;
1582
1583 last = figure->vertex_count - 1;
1584 if (!triangles_only)
1585 {
1586 while (last && figure->vertex_types[last] == D2D_VERTEX_TYPE_NONE)
1587 --last;
1588 }
1589 p0 = &figure->vertices[last];
1590 for (j = 0; j <= last; ++j)
1591 {
1592 if (!triangles_only && figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE)
1593 continue;
1594
1595 p1 = &figure->vertices[j];
1596 d2d_point_subtract(&v_p, p1, p0);
1597 d2d_point_subtract(&v_probe, probe, p0);
1598
1599 if ((probe->y < p0->y) != (probe->y < p1->y) && v_probe.x < v_p.x * (v_probe.y / v_p.y))
1600 {
1601 if (geometry->u.path.fill_mode == D2D1_FILL_MODE_ALTERNATE || (probe->y < p0->y))
1602 ++score;
1603 else
1604 --score;
1605 }
1606
1607 p0 = p1;
1608 }
1609 }
1610
1611 return geometry->u.path.fill_mode == D2D1_FILL_MODE_ALTERNATE ? score & 1 : score;
1612}
1613
1614static BOOL d2d_path_geometry_add_fill_face(struct d2d_geometry *geometry, const struct d2d_cdt *cdt,
1615 const struct d2d_cdt_edge_ref *base_edge)
1616{
1617 struct d2d_cdt_edge_ref tmp;
1618 struct d2d_face *face;
1619 D2D1_POINT_2F probe;
1620
1621 if (cdt->edges[base_edge->idx].flags & D2D_CDT_EDGE_FLAG_VISITED(base_edge->r))
1622 return TRUE;
1623
1624 if (!d2d_array_reserve((void **)&geometry->fill.faces, &geometry->fill.faces_size,
1625 geometry->fill.face_count + 1, sizeof(*geometry->fill.faces)))
1626 {
1627 ERR("Failed to grow faces array.\n");
1628 return FALSE;
1629 }
1630
1631 face = &geometry->fill.faces[geometry->fill.face_count];
1632
1633 /* It may seem tempting to use the center of the face as probe origin, but
1634 * multiplying by powers of two works much better for preserving accuracy. */
1635
1636 tmp = *base_edge;
1637 cdt->edges[tmp.idx].flags |= D2D_CDT_EDGE_FLAG_VISITED(tmp.r);
1638 face->v[0] = d2d_cdt_edge_origin(cdt, &tmp);
1639 probe.x = cdt->vertices[d2d_cdt_edge_origin(cdt, &tmp)].x * 0.25f;
1640 probe.y = cdt->vertices[d2d_cdt_edge_origin(cdt, &tmp)].y * 0.25f;
1641
1642 d2d_cdt_edge_next_left(cdt, &tmp, &tmp);
1643 cdt->edges[tmp.idx].flags |= D2D_CDT_EDGE_FLAG_VISITED(tmp.r);
1644 face->v[1] = d2d_cdt_edge_origin(cdt, &tmp);
1645 probe.x += cdt->vertices[d2d_cdt_edge_origin(cdt, &tmp)].x * 0.25f;
1646 probe.y += cdt->vertices[d2d_cdt_edge_origin(cdt, &tmp)].y * 0.25f;
1647
1648 d2d_cdt_edge_next_left(cdt, &tmp, &tmp);
1649 cdt->edges[tmp.idx].flags |= D2D_CDT_EDGE_FLAG_VISITED(tmp.r);
1650 face->v[2] = d2d_cdt_edge_origin(cdt, &tmp);
1651 probe.x += cdt->vertices[d2d_cdt_edge_origin(cdt, &tmp)].x * 0.50f;
1652 probe.y += cdt->vertices[d2d_cdt_edge_origin(cdt, &tmp)].y * 0.50f;
1653
1654 if (d2d_cdt_leftof(cdt, face->v[2], base_edge) && d2d_path_geometry_point_inside(geometry, &probe, TRUE))
1655 ++geometry->fill.face_count;
1656
1657 return TRUE;
1658}
1659
1660static BOOL d2d_cdt_generate_faces(const struct d2d_cdt *cdt, struct d2d_geometry *geometry)
1661{
1662 struct d2d_cdt_edge_ref base_edge;
1663 size_t i;
1664
1665 for (i = 0; i < cdt->edge_count; ++i)
1666 {
1667 if (cdt->edges[i].flags & D2D_CDT_EDGE_FLAG_FREED)
1668 continue;
1669
1670 base_edge.idx = i;
1671 base_edge.r = 0;
1672 if (!d2d_path_geometry_add_fill_face(geometry, cdt, &base_edge))
1673 goto fail;
1674 d2d_cdt_edge_sym(&base_edge, &base_edge);
1675 if (!d2d_path_geometry_add_fill_face(geometry, cdt, &base_edge))
1676 goto fail;
1677 }
1678
1679 return TRUE;
1680
1681fail:
1682 free(geometry->fill.faces);
1683 geometry->fill.faces = NULL;
1684 geometry->fill.faces_size = 0;
1685 geometry->fill.face_count = 0;
1686 return FALSE;
1687}
1688
1689static BOOL d2d_cdt_fixup(struct d2d_cdt *cdt, const struct d2d_cdt_edge_ref *base_edge)
1690{
1691 struct d2d_cdt_edge_ref candidate, next, new_base;
1692 unsigned int count = 0;
1693
1694 d2d_cdt_edge_next_left(cdt, &next, base_edge);
1695 if (next.idx == base_edge->idx)
1696 {
1697 ERR("Degenerate face.\n");
1698 return FALSE;
1699 }
1700
1701 candidate = next;
1702 while (d2d_cdt_edge_destination(cdt, &next) != d2d_cdt_edge_origin(cdt, base_edge))
1703 {
1704 if (d2d_cdt_incircle(cdt, d2d_cdt_edge_origin(cdt, base_edge), d2d_cdt_edge_destination(cdt, base_edge),
1705 d2d_cdt_edge_destination(cdt, &candidate), d2d_cdt_edge_destination(cdt, &next)))
1706 candidate = next;
1708 ++count;
1709 }
1710
1711 if (count > 1)
1712 {
1713 d2d_cdt_edge_next_left(cdt, &next, &candidate);
1714 if (d2d_cdt_edge_destination(cdt, &next) == d2d_cdt_edge_origin(cdt, base_edge))
1715 d2d_cdt_edge_next_left(cdt, &next, base_edge);
1716 else
1717 next = *base_edge;
1718 if (!d2d_cdt_connect(cdt, &new_base, &candidate, &next))
1719 return FALSE;
1720 if (!d2d_cdt_fixup(cdt, &new_base))
1721 return FALSE;
1722 d2d_cdt_edge_sym(&new_base, &new_base);
1723 if (!d2d_cdt_fixup(cdt, &new_base))
1724 return FALSE;
1725 }
1726
1727 return TRUE;
1728}
1729
1730static void d2d_cdt_cut_edges(struct d2d_cdt *cdt, struct d2d_cdt_edge_ref *end_edge,
1731 const struct d2d_cdt_edge_ref *base_edge, size_t start_vertex, size_t end_vertex)
1732{
1733 struct d2d_cdt_edge_ref next;
1734 float ccw;
1735
1736 d2d_cdt_edge_next_left(cdt, &next, base_edge);
1737 if (d2d_cdt_edge_destination(cdt, &next) == end_vertex)
1738 {
1739 *end_edge = next;
1740 return;
1741 }
1742
1743 ccw = d2d_cdt_ccw(cdt, d2d_cdt_edge_destination(cdt, &next), end_vertex, start_vertex);
1744 if (ccw == 0.0f)
1745 {
1746 *end_edge = next;
1747 return;
1748 }
1749
1750 if (ccw > 0.0f)
1752
1754 d2d_cdt_cut_edges(cdt, end_edge, &next, start_vertex, end_vertex);
1756}
1757
1758static BOOL d2d_cdt_insert_segment(struct d2d_cdt *cdt, struct d2d_geometry *geometry,
1759 const struct d2d_cdt_edge_ref *origin, struct d2d_cdt_edge_ref *edge, size_t end_vertex)
1760{
1761 struct d2d_cdt_edge_ref base_edge, current, new_origin, next, target;
1762 size_t current_destination, current_origin;
1763
1764 for (current = *origin;; current = next)
1765 {
1767
1768 current_destination = d2d_cdt_edge_destination(cdt, &current);
1769 if (current_destination == end_vertex)
1770 {
1771 d2d_cdt_edge_sym(edge, &current);
1772 return TRUE;
1773 }
1774
1775 current_origin = d2d_cdt_edge_origin(cdt, &current);
1776 if (d2d_cdt_ccw(cdt, end_vertex, current_origin, current_destination) == 0.0f
1777 && (cdt->vertices[current_destination].x > cdt->vertices[current_origin].x)
1778 == (cdt->vertices[end_vertex].x > cdt->vertices[current_origin].x)
1779 && (cdt->vertices[current_destination].y > cdt->vertices[current_origin].y)
1780 == (cdt->vertices[end_vertex].y > cdt->vertices[current_origin].y))
1781 {
1782 d2d_cdt_edge_sym(&new_origin, &current);
1783 return d2d_cdt_insert_segment(cdt, geometry, &new_origin, edge, end_vertex);
1784 }
1785
1786 if (d2d_cdt_rightof(cdt, end_vertex, &next) && d2d_cdt_leftof(cdt, end_vertex, &current))
1787 {
1788 d2d_cdt_edge_next_left(cdt, &base_edge, &current);
1789
1790 d2d_cdt_edge_sym(&base_edge, &base_edge);
1791 d2d_cdt_cut_edges(cdt, &target, &base_edge, d2d_cdt_edge_origin(cdt, origin), end_vertex);
1792 d2d_cdt_destroy_edge(cdt, &base_edge);
1793
1794 if (!d2d_cdt_connect(cdt, &base_edge, &target, &current))
1795 return FALSE;
1796 *edge = base_edge;
1797 if (!d2d_cdt_fixup(cdt, &base_edge))
1798 return FALSE;
1799 d2d_cdt_edge_sym(&base_edge, &base_edge);
1800 if (!d2d_cdt_fixup(cdt, &base_edge))
1801 return FALSE;
1802
1803 if (d2d_cdt_edge_origin(cdt, edge) == end_vertex)
1804 return TRUE;
1805 new_origin = *edge;
1806 return d2d_cdt_insert_segment(cdt, geometry, &new_origin, edge, end_vertex);
1807 }
1808
1809 if (next.idx == origin->idx)
1810 {
1811 ERR("Triangle not found.\n");
1812 return FALSE;
1813 }
1814 }
1815}
1816
1817static BOOL d2d_cdt_insert_segments(struct d2d_cdt *cdt, struct d2d_geometry *geometry)
1818{
1819 size_t start_vertex, end_vertex, i, j, k;
1820 struct d2d_cdt_edge_ref edge, new_edge;
1821 const struct d2d_figure *figure;
1822 const D2D1_POINT_2F *p;
1823 BOOL found;
1824
1825 for (i = 0; i < geometry->u.path.figure_count; ++i)
1826 {
1827 figure = &geometry->u.path.figures[i];
1828
1829 if (figure->flags & D2D_FIGURE_FLAG_HOLLOW)
1830 continue;
1831
1832 /* Degenerate figure. */
1833 if (figure->vertex_count < 2)
1834 continue;
1835
1836 p = bsearch(&figure->vertices[figure->vertex_count - 1], cdt->vertices,
1837 geometry->fill.vertex_count, sizeof(*p), d2d_cdt_compare_vertices);
1838 start_vertex = p - cdt->vertices;
1839
1840 for (k = 0, found = FALSE; k < cdt->edge_count; ++k)
1841 {
1842 if (cdt->edges[k].flags & D2D_CDT_EDGE_FLAG_FREED)
1843 continue;
1844
1845 edge.idx = k;
1846 edge.r = 0;
1847
1848 if (d2d_cdt_edge_origin(cdt, &edge) == start_vertex)
1849 {
1850 found = TRUE;
1851 break;
1852 }
1853 d2d_cdt_edge_sym(&edge, &edge);
1854 if (d2d_cdt_edge_origin(cdt, &edge) == start_vertex)
1855 {
1856 found = TRUE;
1857 break;
1858 }
1859 }
1860
1861 if (!found)
1862 {
1863 ERR("Edge not found.\n");
1864 return FALSE;
1865 }
1866
1867 for (j = 0; j < figure->vertex_count; start_vertex = end_vertex, ++j)
1868 {
1869 p = bsearch(&figure->vertices[j], cdt->vertices,
1870 geometry->fill.vertex_count, sizeof(*p), d2d_cdt_compare_vertices);
1871 end_vertex = p - cdt->vertices;
1872
1873 if (start_vertex == end_vertex)
1874 continue;
1875
1876 if (!d2d_cdt_insert_segment(cdt, geometry, &edge, &new_edge, end_vertex))
1877 return FALSE;
1878 edge = new_edge;
1879 }
1880 }
1881
1882 return TRUE;
1883}
1884
1886 const struct d2d_segment_idx *segment_idx, float t, D2D1_POINT_2F p)
1887{
1888 struct d2d_geometry_intersection *intersection;
1889
1890 if (!d2d_array_reserve((void **)&i->intersections, &i->intersections_size,
1891 i->intersection_count + 1, sizeof(*i->intersections)))
1892 {
1893 ERR("Failed to grow intersections array.\n");
1894 return FALSE;
1895 }
1896
1897 intersection = &i->intersections[i->intersection_count++];
1898 intersection->figure_idx = segment_idx->figure_idx;
1899 intersection->vertex_idx = segment_idx->vertex_idx;
1900 intersection->control_idx = segment_idx->control_idx;
1901 intersection->t = t;
1902 intersection->p = p;
1903
1904 return TRUE;
1905}
1906
1907static int __cdecl d2d_geometry_intersections_compare(const void *a, const void *b)
1908{
1909 const struct d2d_geometry_intersection *i0 = a;
1910 const struct d2d_geometry_intersection *i1 = b;
1911
1912 if (i0->figure_idx != i1->figure_idx)
1913 return i0->figure_idx - i1->figure_idx;
1914 if (i0->vertex_idx != i1->vertex_idx)
1915 return i0->vertex_idx - i1->vertex_idx;
1916 if (i0->t != i1->t)
1917 return i0->t > i1->t ? 1 : -1;
1918 return 0;
1919}
1920
1922 struct d2d_geometry_intersections *intersections, const struct d2d_segment_idx *idx_p,
1923 const struct d2d_segment_idx *idx_q)
1924{
1925 D2D1_POINT_2F v_p, v_q, v_qp, intersection;
1926 const D2D1_POINT_2F *p[2], *q[2];
1927 const struct d2d_figure *figure;
1928 float s, t, det;
1929 size_t next;
1930
1931 figure = &geometry->u.path.figures[idx_p->figure_idx];
1932 p[0] = &figure->vertices[idx_p->vertex_idx];
1933 next = idx_p->vertex_idx + 1;
1934 if (next == figure->vertex_count)
1935 next = 0;
1936 p[1] = &figure->vertices[next];
1937
1938 figure = &geometry->u.path.figures[idx_q->figure_idx];
1939 q[0] = &figure->vertices[idx_q->vertex_idx];
1940 next = idx_q->vertex_idx + 1;
1941 if (next == figure->vertex_count)
1942 next = 0;
1943 q[1] = &figure->vertices[next];
1944
1945 d2d_point_subtract(&v_p, p[1], p[0]);
1946 d2d_point_subtract(&v_q, q[1], q[0]);
1947 d2d_point_subtract(&v_qp, p[0], q[0]);
1948
1949 det = v_p.x * v_q.y - v_p.y * v_q.x;
1950 if (det == 0.0f)
1951 return TRUE;
1952
1953 s = (v_q.x * v_qp.y - v_q.y * v_qp.x) / det;
1954 t = (v_p.x * v_qp.y - v_p.y * v_qp.x) / det;
1955
1956 if (s < 0.0f || s > 1.0f || t < 0.0f || t > 1.0f)
1957 return TRUE;
1958
1959 intersection.x = p[0]->x + v_p.x * s;
1960 intersection.y = p[0]->y + v_p.y * s;
1961
1962 if (s > 0.0f && s < 1.0f && !d2d_geometry_intersections_add(intersections, idx_p, s, intersection))
1963 return FALSE;
1964
1965 if (t > 0.0f && t < 1.0f && !d2d_geometry_intersections_add(intersections, idx_q, t, intersection))
1966 return FALSE;
1967
1968 return TRUE;
1969}
1970
1972 struct d2d_geometry_intersections *intersections, const struct d2d_segment_idx *idx_p,
1973 const D2D1_POINT_2F **p, const struct d2d_segment_idx *idx_q, const D2D1_POINT_2F **q, float s)
1974{
1975 D2D1_POINT_2F intersection;
1976 float t;
1977
1978 d2d_point_calculate_bezier(&intersection, p[0], p[1], p[2], s);
1979 if (fabsf(q[1]->x - q[0]->x) > fabsf(q[1]->y - q[0]->y))
1980 t = (intersection.x - q[0]->x) / (q[1]->x - q[0]->x);
1981 else
1982 t = (intersection.y - q[0]->y) / (q[1]->y - q[0]->y);
1983 if (t < 0.0f || t > 1.0f)
1984 return TRUE;
1985
1986 d2d_point_lerp(&intersection, q[0], q[1], t);
1987
1988 if (s > 0.0f && s < 1.0f && !d2d_geometry_intersections_add(intersections, idx_p, s, intersection))
1989 return FALSE;
1990
1991 if (t > 0.0f && t < 1.0f && !d2d_geometry_intersections_add(intersections, idx_q, t, intersection))
1992 return FALSE;
1993
1994 return TRUE;
1995}
1996
1998 struct d2d_geometry_intersections *intersections,
1999 const struct d2d_segment_idx *idx_p, const struct d2d_segment_idx *idx_q)
2000{
2001 const D2D1_POINT_2F *p[3], *q[2];
2002 const struct d2d_figure *figure;
2003 float y[3], root, theta, d, e;
2004 size_t next;
2005
2006 figure = &geometry->u.path.figures[idx_p->figure_idx];
2007 p[0] = &figure->vertices[idx_p->vertex_idx];
2008 p[1] = &figure->bezier_controls[idx_p->control_idx];
2009 next = idx_p->vertex_idx + 1;
2010 p[2] = &figure->vertices[next];
2011
2012 figure = &geometry->u.path.figures[idx_q->figure_idx];
2013 q[0] = &figure->vertices[idx_q->vertex_idx];
2014 next = idx_q->vertex_idx + 1;
2015 if (next == figure->vertex_count)
2016 next = 0;
2017 q[1] = &figure->vertices[next];
2018
2019 /* Align the line with x-axis. */
2020 theta = -atan2f(q[1]->y - q[0]->y, q[1]->x - q[0]->x);
2021 y[0] = (p[0]->x - q[0]->x) * sinf(theta) + (p[0]->y - q[0]->y) * cosf(theta);
2022 y[1] = (p[1]->x - q[0]->x) * sinf(theta) + (p[1]->y - q[0]->y) * cosf(theta);
2023 y[2] = (p[2]->x - q[0]->x) * sinf(theta) + (p[2]->y - q[0]->y) * cosf(theta);
2024
2025 /* Intersect the transformed curve with the x-axis.
2026 *
2027 * f(t) = (1 - t)²P₀ + 2(1 - t)tP₁ + t²P₂
2028 * = (P₀ - 2P₁ + P₂)t² + 2(P₁ - P₀)t + P₀
2029 *
2030 * a = P₀ - 2P₁ + P₂
2031 * b = 2(P₁ - P₀)
2032 * c = P₀
2033 *
2034 * f(t) = 0
2035 * t = (-b ± √(b² - 4ac)) / 2a
2036 * = (-2(P₁ - P₀) ± √((2(P₁ - P₀))² - 4((P₀ - 2P₁ + P₂)P₀))) / 2(P₀ - 2P₁ + P₂)
2037 * = (2P₀ - 2P₁ ± √(4P₀² + 4P₁² - 8P₀P₁ - 4P₀² + 8P₀P₁ - 4P₀P₂)) / (2P₀ - 4P₁ + 2P₂)
2038 * = (P₀ - P₁ ± √(P₁² - P₀P₂)) / (P₀ - 2P₁ + P₂) */
2039
2040 d = y[0] - 2 * y[1] + y[2];
2041 if (d == 0.0f)
2042 {
2043 /* P₀ - 2P₁ + P₂ = 0
2044 * f(t) = (P₀ - 2P₁ + P₂)t² + 2(P₁ - P₀)t + P₀ = 0
2045 * t = -P₀ / 2(P₁ - P₀) */
2046 root = -y[0] / (2.0f * (y[1] - y[0]));
2047 if (root < 0.0f || root > 1.0f)
2048 return TRUE;
2049
2050 return d2d_geometry_add_bezier_line_intersections(geometry, intersections, idx_p, p, idx_q, q, root);
2051 }
2052
2053 e = y[1] * y[1] - y[0] * y[2];
2054 if (e < 0.0f)
2055 return TRUE;
2056
2057 root = (y[0] - y[1] + sqrtf(e)) / d;
2058 if (root >= 0.0f && root <= 1.0f && !d2d_geometry_add_bezier_line_intersections(geometry,
2059 intersections, idx_p, p, idx_q, q, root))
2060 return FALSE;
2061
2062 root = (y[0] - y[1] - sqrtf(e)) / d;
2063 if (root >= 0.0f && root <= 1.0f && !d2d_geometry_add_bezier_line_intersections(geometry,
2064 intersections, idx_p, p, idx_q, q, root))
2065 return FALSE;
2066
2067 return TRUE;
2068}
2069
2071 struct d2d_geometry_intersections *intersections,
2072 const struct d2d_segment_idx *idx_p, float start_p, float end_p,
2073 const struct d2d_segment_idx *idx_q, float start_q, float end_q)
2074{
2075 const D2D1_POINT_2F *p[3], *q[3];
2076 const struct d2d_figure *figure;
2077 D2D_RECT_F p_bounds, q_bounds;
2078 D2D1_POINT_2F intersection;
2079 float centre_p, centre_q;
2080 size_t next;
2081
2082 figure = &geometry->u.path.figures[idx_p->figure_idx];
2083 p[0] = &figure->vertices[idx_p->vertex_idx];
2084 p[1] = &figure->bezier_controls[idx_p->control_idx];
2085 next = idx_p->vertex_idx + 1;
2086 p[2] = &figure->vertices[next];
2087
2088 figure = &geometry->u.path.figures[idx_q->figure_idx];
2089 q[0] = &figure->vertices[idx_q->vertex_idx];
2090 q[1] = &figure->bezier_controls[idx_q->control_idx];
2091 next = idx_q->vertex_idx + 1;
2092 q[2] = &figure->vertices[next];
2093
2094 d2d_rect_get_bezier_segment_bounds(&p_bounds, p[0], p[1], p[2], start_p, end_p);
2095 d2d_rect_get_bezier_segment_bounds(&q_bounds, q[0], q[1], q[2], start_q, end_q);
2096
2097 if (!d2d_rect_check_overlap(&p_bounds, &q_bounds))
2098 return TRUE;
2099
2100 centre_p = (start_p + end_p) / 2.0f;
2101 centre_q = (start_q + end_q) / 2.0f;
2102
2103 if (end_p - start_p < 1e-3f)
2104 {
2105 d2d_point_calculate_bezier(&intersection, p[0], p[1], p[2], centre_p);
2106 if (start_p > 0.0f && end_p < 1.0f && !d2d_geometry_intersections_add(intersections,
2107 idx_p, centre_p, intersection))
2108 return FALSE;
2109 if (start_q > 0.0f && end_q < 1.0f && !d2d_geometry_intersections_add(intersections,
2110 idx_q, centre_q, intersection))
2111 return FALSE;
2112 return TRUE;
2113 }
2114
2115 if (!d2d_geometry_intersect_bezier_bezier(geometry, intersections,
2116 idx_p, start_p, centre_p, idx_q, start_q, centre_q))
2117 return FALSE;
2118 if (!d2d_geometry_intersect_bezier_bezier(geometry, intersections,
2119 idx_p, start_p, centre_p, idx_q, centre_q, end_q))
2120 return FALSE;
2121 if (!d2d_geometry_intersect_bezier_bezier(geometry, intersections,
2122 idx_p, centre_p, end_p, idx_q, start_q, centre_q))
2123 return FALSE;
2124 if (!d2d_geometry_intersect_bezier_bezier(geometry, intersections,
2125 idx_p, centre_p, end_p, idx_q, centre_q, end_q))
2126 return FALSE;
2127
2128 return TRUE;
2129}
2130
2132 struct d2d_geometry_intersections *intersections)
2133{
2134 size_t vertex_offset, control_offset, next, i;
2135 struct d2d_geometry_intersection *inter;
2136 enum d2d_vertex_type vertex_type;
2137 const D2D1_POINT_2F *p[3];
2138 struct d2d_figure *figure;
2139 D2D1_POINT_2F q[2];
2140 float t, t_prev;
2141
2142 for (i = 0; i < intersections->intersection_count; ++i)
2143 {
2144 inter = &intersections->intersections[i];
2145 if (!i || inter->figure_idx != intersections->intersections[i - 1].figure_idx)
2146 vertex_offset = control_offset = 0;
2147
2148 figure = &geometry->u.path.figures[inter->figure_idx];
2149 vertex_type = figure->vertex_types[inter->vertex_idx + vertex_offset];
2150 if (!d2d_vertex_type_is_bezier(vertex_type))
2151 {
2152 if (!d2d_figure_insert_vertex(&geometry->u.path.figures[inter->figure_idx],
2153 inter->vertex_idx + vertex_offset + 1, inter->p))
2154 return FALSE;
2155 ++vertex_offset;
2156 continue;
2157 }
2158
2159 t = inter->t;
2160 if (i && inter->figure_idx == intersections->intersections[i - 1].figure_idx
2161 && inter->vertex_idx == intersections->intersections[i - 1].vertex_idx)
2162 {
2163 t_prev = intersections->intersections[i - 1].t;
2164 if (t - t_prev < 1e-3f)
2165 {
2166 inter->t = intersections->intersections[i - 1].t;
2167 continue;
2168 }
2169 t = (t - t_prev) / (1.0f - t_prev);
2170 }
2171
2172 p[0] = &figure->vertices[inter->vertex_idx + vertex_offset];
2173 p[1] = &figure->bezier_controls[inter->control_idx + control_offset];
2174 next = inter->vertex_idx + vertex_offset + 1;
2175 p[2] = &figure->vertices[next];
2176
2177 d2d_point_lerp(&q[0], p[0], p[1], t);
2178 d2d_point_lerp(&q[1], p[1], p[2], t);
2179
2180 figure->bezier_controls[inter->control_idx + control_offset] = q[0];
2181 if (!(d2d_figure_insert_bezier_controls(figure, inter->control_idx + control_offset + 1, 1, &q[1])))
2182 return FALSE;
2183 ++control_offset;
2184
2185 if (!(d2d_figure_insert_vertex(figure, inter->vertex_idx + vertex_offset + 1, inter->p)))
2186 return FALSE;
2187 figure->vertex_types[inter->vertex_idx + vertex_offset + 1] = D2D_VERTEX_TYPE_SPLIT_BEZIER;
2188 ++vertex_offset;
2189 }
2190
2191 return TRUE;
2192}
2193
2194/* Intersect the geometry's segments with themselves. This uses the
2195 * straightforward approach of testing everything against everything, but
2196 * there certainly exist more scalable algorithms for this. */
2198{
2200 const struct d2d_figure *figure_p, *figure_q;
2201 struct d2d_segment_idx idx_p, idx_q;
2202 enum d2d_vertex_type type_p, type_q;
2203 BOOL ret = FALSE;
2204 size_t max_q;
2205
2206 if (!geometry->u.path.figure_count)
2207 return TRUE;
2208
2209 for (idx_p.figure_idx = 0; idx_p.figure_idx < geometry->u.path.figure_count; ++idx_p.figure_idx)
2210 {
2211 figure_p = &geometry->u.path.figures[idx_p.figure_idx];
2212 idx_p.control_idx = 0;
2213 for (idx_p.vertex_idx = 0; idx_p.vertex_idx < figure_p->vertex_count; ++idx_p.vertex_idx)
2214 {
2215 if ((type_p = figure_p->vertex_types[idx_p.vertex_idx]) == D2D_VERTEX_TYPE_END)
2216 continue;
2217
2218 for (idx_q.figure_idx = 0; idx_q.figure_idx <= idx_p.figure_idx; ++idx_q.figure_idx)
2219 {
2220 figure_q = &geometry->u.path.figures[idx_q.figure_idx];
2221 if (idx_q.figure_idx != idx_p.figure_idx)
2222 {
2223 if (!d2d_rect_check_overlap(&figure_p->bounds, &figure_q->bounds))
2224 continue;
2225 if ((max_q = figure_q->vertex_count)
2226 && figure_q->vertex_types[max_q - 1] == D2D_VERTEX_TYPE_END)
2227 --max_q;
2228 }
2229 else
2230 {
2231 max_q = idx_p.vertex_idx;
2232 }
2233
2234 idx_q.control_idx = 0;
2235 for (idx_q.vertex_idx = 0; idx_q.vertex_idx < max_q; ++idx_q.vertex_idx)
2236 {
2237 type_q = figure_q->vertex_types[idx_q.vertex_idx];
2238 if (d2d_vertex_type_is_bezier(type_q))
2239 {
2240 if (d2d_vertex_type_is_bezier(type_p))
2241 {
2242 if (!d2d_geometry_intersect_bezier_bezier(geometry, &intersections,
2243 &idx_p, 0.0f, 1.0f, &idx_q, 0.0f, 1.0f))
2244 goto done;
2245 }
2246 else
2247 {
2248 if (!d2d_geometry_intersect_bezier_line(geometry, &intersections, &idx_q, &idx_p))
2249 goto done;
2250 }
2251 ++idx_q.control_idx;
2252 }
2253 else
2254 {
2255 if (d2d_vertex_type_is_bezier(type_p))
2256 {
2257 if (!d2d_geometry_intersect_bezier_line(geometry, &intersections, &idx_p, &idx_q))
2258 goto done;
2259 }
2260 else
2261 {
2262 if (!d2d_geometry_intersect_line_line(geometry, &intersections, &idx_p, &idx_q))
2263 goto done;
2264 }
2265 }
2266 }
2267 }
2268 if (d2d_vertex_type_is_bezier(type_p))
2269 ++idx_p.control_idx;
2270 }
2271 }
2272
2273 qsort(intersections.intersections, intersections.intersection_count,
2274 sizeof(*intersections.intersections), d2d_geometry_intersections_compare);
2275 ret = d2d_geometry_apply_intersections(geometry, &intersections);
2276
2277done:
2278 free(intersections.intersections);
2279 return ret;
2280}
2281
2283{
2284 struct d2d_cdt_edge_ref left_edge, right_edge;
2285 size_t vertex_count, i, j;
2286 struct d2d_cdt cdt = {0};
2288#ifdef __i386__
2289 unsigned int control_word_x87, mask = 0;
2290#endif
2291
2292 for (i = 0, vertex_count = 0; i < geometry->u.path.figure_count; ++i)
2293 {
2294 if (geometry->u.path.figures[i].flags & D2D_FIGURE_FLAG_HOLLOW)
2295 continue;
2296 vertex_count += geometry->u.path.figures[i].vertex_count;
2297 }
2298
2299 if (vertex_count < 3)
2300 {
2301 WARN("Geometry has %lu vertices.\n", (long)vertex_count);
2302 return S_OK;
2303 }
2304
2305 if (!(vertices = calloc(vertex_count, sizeof(*vertices))))
2306 return E_OUTOFMEMORY;
2307
2308 for (i = 0, j = 0; i < geometry->u.path.figure_count; ++i)
2309 {
2310 if (geometry->u.path.figures[i].flags & D2D_FIGURE_FLAG_HOLLOW)
2311 continue;
2312 memcpy(&vertices[j], geometry->u.path.figures[i].vertices,
2313 geometry->u.path.figures[i].vertex_count * sizeof(*vertices));
2314 j += geometry->u.path.figures[i].vertex_count;
2315 }
2316
2317 /* Sort vertices, eliminate duplicates. */
2319 for (i = 1; i < vertex_count; ++i)
2320 {
2321 if (!memcmp(&vertices[i - 1], &vertices[i], sizeof(*vertices)))
2322 {
2323 --vertex_count;
2324 memmove(&vertices[i], &vertices[i + 1], (vertex_count - i) * sizeof(*vertices));
2325 --i;
2326 }
2327 }
2328
2329 if (vertex_count < 3)
2330 {
2331 WARN("Geometry has %lu vertices after eliminating duplicates.\n", (long)vertex_count);
2332 free(vertices);
2333 return S_OK;
2334 }
2335
2336 geometry->fill.vertices = vertices;
2337 geometry->fill.vertex_count = vertex_count;
2338
2339 cdt.free_edge = ~0u;
2340 cdt.vertices = vertices;
2341
2342#ifdef __i386__
2343 control_word_x87 = _controlfp(0, 0);
2345#endif
2346 if (!d2d_cdt_triangulate(&cdt, 0, vertex_count, &left_edge, &right_edge))
2347 goto fail;
2348 if (!d2d_cdt_insert_segments(&cdt, geometry))
2349 goto fail;
2350#ifdef __i386__
2351 _controlfp(control_word_x87, _MCW_PC);
2352 mask = 0;
2353#endif
2354
2355 if (!d2d_cdt_generate_faces(&cdt, geometry))
2356 goto fail;
2357
2358 free(cdt.edges);
2359 return S_OK;
2360
2361fail:
2362 geometry->fill.vertices = NULL;
2363 geometry->fill.vertex_count = 0;
2364 free(vertices);
2365 free(cdt.edges);
2366#ifdef __i386__
2367 if (mask) _controlfp(control_word_x87, mask);
2368#endif
2369 return E_FAIL;
2370}
2371
2373{
2374 struct d2d_figure *figure;
2375
2376 if (!d2d_array_reserve((void **)&geometry->u.path.figures, &geometry->u.path.figures_size,
2377 geometry->u.path.figure_count + 1, sizeof(*geometry->u.path.figures)))
2378 {
2379 ERR("Failed to grow figures array.\n");
2380 return FALSE;
2381 }
2382
2383 figure = &geometry->u.path.figures[geometry->u.path.figure_count];
2384 memset(figure, 0, sizeof(*figure));
2385 figure->bounds.left = FLT_MAX;
2386 figure->bounds.top = FLT_MAX;
2387 figure->bounds.right = -FLT_MAX;
2388 figure->bounds.bottom = -FLT_MAX;
2389
2390 ++geometry->u.path.figure_count;
2391 return TRUE;
2392}
2393
2395 const D2D1_POINT_2F *prev, const D2D1_POINT_2F *p0, const D2D1_POINT_2F *next)
2396{
2397 static const D2D1_POINT_2F origin = {0.0f, 0.0f};
2398 struct d2d_outline_vertex *v;
2399 struct d2d_face *f;
2400 size_t base_idx;
2401 float ccw;
2402
2403 if (!d2d_array_reserve((void **)&geometry->outline.vertices, &geometry->outline.vertices_size,
2404 geometry->outline.vertex_count + 4, sizeof(*geometry->outline.vertices)))
2405 {
2406 ERR("Failed to grow outline vertices array.\n");
2407 return FALSE;
2408 }
2409 base_idx = geometry->outline.vertex_count;
2410 v = &geometry->outline.vertices[base_idx];
2411
2412 if (!d2d_array_reserve((void **)&geometry->outline.faces, &geometry->outline.faces_size,
2413 geometry->outline.face_count + 2, sizeof(*geometry->outline.faces)))
2414 {
2415 ERR("Failed to grow outline faces array.\n");
2416 return FALSE;
2417 }
2418 f = &geometry->outline.faces[geometry->outline.face_count];
2419
2420 ccw = d2d_point_ccw(&origin, prev, next);
2421 if (ccw == 0.0f)
2422 {
2423 d2d_outline_vertex_set(&v[0], p0->x, p0->y, -prev->x, -prev->y, -prev->x, -prev->y);
2424 d2d_outline_vertex_set(&v[1], p0->x, p0->y, prev->x, prev->y, prev->x, prev->y);
2425 d2d_outline_vertex_set(&v[2], p0->x + 25.0f * -prev->x, p0->y + 25.0f * -prev->y,
2426 prev->x, prev->y, prev->x, prev->y);
2427 d2d_outline_vertex_set(&v[3], p0->x + 25.0f * -prev->x, p0->y + 25.0f * -prev->y,
2428 -prev->x, -prev->y, -prev->x, -prev->y);
2429 }
2430 else if (ccw < 0.0f)
2431 {
2432 d2d_outline_vertex_set(&v[0], p0->x, p0->y, next->x, next->y, -prev->x, -prev->y);
2433 d2d_outline_vertex_set(&v[1], p0->x, p0->y, -next->x, -next->y, -next->x, -next->y);
2434 d2d_outline_vertex_set(&v[2], p0->x, p0->y, -next->x, -next->y, prev->x, prev->y);
2435 d2d_outline_vertex_set(&v[3], p0->x, p0->y, prev->x, prev->y, prev->x, prev->y);
2436 }
2437 else
2438 {
2439 d2d_outline_vertex_set(&v[0], p0->x, p0->y, prev->x, prev->y, -next->x, -next->y);
2440 d2d_outline_vertex_set(&v[1], p0->x, p0->y, -prev->x, -prev->y, -prev->x, -prev->y);
2441 d2d_outline_vertex_set(&v[2], p0->x, p0->y, -prev->x, -prev->y, next->x, next->y);
2442 d2d_outline_vertex_set(&v[3], p0->x, p0->y, next->x, next->y, next->x, next->y);
2443 }
2444 geometry->outline.vertex_count += 4;
2445
2446 d2d_face_set(&f[0], base_idx + 1, base_idx + 0, base_idx + 2);
2447 d2d_face_set(&f[1], base_idx + 2, base_idx + 0, base_idx + 3);
2448 geometry->outline.face_count += 2;
2449
2450 return TRUE;
2451}
2452
2454 const D2D1_POINT_2F *p0, const D2D1_POINT_2F *next)
2455{
2456 struct d2d_outline_vertex *v;
2457 D2D1_POINT_2F q_next;
2458 struct d2d_face *f;
2459 size_t base_idx;
2460
2461 if (!d2d_array_reserve((void **)&geometry->outline.vertices, &geometry->outline.vertices_size,
2462 geometry->outline.vertex_count + 4, sizeof(*geometry->outline.vertices)))
2463 {
2464 ERR("Failed to grow outline vertices array.\n");
2465 return FALSE;
2466 }
2467 base_idx = geometry->outline.vertex_count;
2468 v = &geometry->outline.vertices[base_idx];
2469
2470 if (!d2d_array_reserve((void **)&geometry->outline.faces, &geometry->outline.faces_size,
2471 geometry->outline.face_count + 2, sizeof(*geometry->outline.faces)))
2472 {
2473 ERR("Failed to grow outline faces array.\n");
2474 return FALSE;
2475 }
2476 f = &geometry->outline.faces[geometry->outline.face_count];
2477
2478 d2d_point_subtract(&q_next, next, p0);
2479 d2d_point_normalise(&q_next);
2480
2481 d2d_outline_vertex_set(&v[0], p0->x, p0->y, q_next.x, q_next.y, q_next.x, q_next.y);
2482 d2d_outline_vertex_set(&v[1], p0->x, p0->y, -q_next.x, -q_next.y, -q_next.x, -q_next.y);
2483 d2d_outline_vertex_set(&v[2], next->x, next->y, q_next.x, q_next.y, q_next.x, q_next.y);
2484 d2d_outline_vertex_set(&v[3], next->x, next->y, -q_next.x, -q_next.y, -q_next.x, -q_next.y);
2485 geometry->outline.vertex_count += 4;
2486
2487 d2d_face_set(&f[0], base_idx + 0, base_idx + 1, base_idx + 2);
2488 d2d_face_set(&f[1], base_idx + 2, base_idx + 1, base_idx + 3);
2489 geometry->outline.face_count += 2;
2490
2491 return TRUE;
2492}
2493
2495 const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2)
2496{
2498 D2D1_POINT_2F r0, r1, r2;
2499 D2D1_POINT_2F q0, q1, q2;
2500 struct d2d_face *f;
2501 size_t base_idx;
2502
2503 if (!d2d_array_reserve((void **)&geometry->outline.beziers, &geometry->outline.beziers_size,
2504 geometry->outline.bezier_count + 7, sizeof(*geometry->outline.beziers)))
2505 {
2506 ERR("Failed to grow outline beziers array.\n");
2507 return FALSE;
2508 }
2509 base_idx = geometry->outline.bezier_count;
2510 b = &geometry->outline.beziers[base_idx];
2511
2512 if (!d2d_array_reserve((void **)&geometry->outline.bezier_faces, &geometry->outline.bezier_faces_size,
2513 geometry->outline.bezier_face_count + 5, sizeof(*geometry->outline.bezier_faces)))
2514 {
2515 ERR("Failed to grow outline faces array.\n");
2516 return FALSE;
2517 }
2518 f = &geometry->outline.bezier_faces[geometry->outline.bezier_face_count];
2519
2520 d2d_point_lerp(&q0, p0, p1, 0.5f);
2521 d2d_point_lerp(&q1, p1, p2, 0.5f);
2522 d2d_point_lerp(&q2, &q0, &q1, 0.5f);
2523
2524 d2d_point_subtract(&r0, &q0, p0);
2525 d2d_point_subtract(&r1, &q1, &q0);
2526 d2d_point_subtract(&r2, p2, &q1);
2527
2531
2532 if (d2d_point_ccw(p0, p1, p2) > 0.0f)
2533 {
2534 d2d_point_scale(&r0, -1.0f);
2535 d2d_point_scale(&r1, -1.0f);
2536 d2d_point_scale(&r2, -1.0f);
2537 }
2538
2539 d2d_curve_outline_vertex_set(&b[0], p0, p0, p1, p2, r0.x, r0.y, r0.x, r0.y);
2540 d2d_curve_outline_vertex_set(&b[1], p0, p0, p1, p2, -r0.x, -r0.y, -r0.x, -r0.y);
2541 d2d_curve_outline_vertex_set(&b[2], &q0, p0, p1, p2, r0.x, r0.y, r1.x, r1.y);
2542 d2d_curve_outline_vertex_set(&b[3], &q2, p0, p1, p2, -r1.x, -r1.y, -r1.x, -r1.y);
2543 d2d_curve_outline_vertex_set(&b[4], &q1, p0, p1, p2, r1.x, r1.y, r2.x, r2.y);
2544 d2d_curve_outline_vertex_set(&b[5], p2, p0, p1, p2, -r2.x, -r2.y, -r2.x, -r2.y);
2545 d2d_curve_outline_vertex_set(&b[6], p2, p0, p1, p2, r2.x, r2.y, r2.x, r2.y);
2546 geometry->outline.bezier_count += 7;
2547
2548 d2d_face_set(&f[0], base_idx + 0, base_idx + 1, base_idx + 2);
2549 d2d_face_set(&f[1], base_idx + 2, base_idx + 1, base_idx + 3);
2550 d2d_face_set(&f[2], base_idx + 3, base_idx + 4, base_idx + 2);
2551 d2d_face_set(&f[3], base_idx + 5, base_idx + 4, base_idx + 3);
2552 d2d_face_set(&f[4], base_idx + 5, base_idx + 6, base_idx + 4);
2553 geometry->outline.bezier_face_count += 5;
2554
2555 return TRUE;
2556}
2557
2559 const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2)
2560{
2562 D2D1_POINT_2F r0, r1;
2563 struct d2d_face *f;
2564 size_t base_idx;
2565
2566 if (!d2d_array_reserve((void **)&geometry->outline.arcs, &geometry->outline.arcs_size,
2567 geometry->outline.arc_count + 5, sizeof(*geometry->outline.arcs)))
2568 {
2569 ERR("Failed to grow outline arcs array.\n");
2570 return FALSE;
2571 }
2572 base_idx = geometry->outline.arc_count;
2573 a = &geometry->outline.arcs[base_idx];
2574
2575 if (!d2d_array_reserve((void **)&geometry->outline.arc_faces, &geometry->outline.arc_faces_size,
2576 geometry->outline.arc_face_count + 3, sizeof(*geometry->outline.arc_faces)))
2577 {
2578 ERR("Failed to grow outline faces array.\n");
2579 return FALSE;
2580 }
2581 f = &geometry->outline.arc_faces[geometry->outline.arc_face_count];
2582
2583 d2d_point_subtract(&r0, p1, p0);
2584 d2d_point_subtract(&r1, p2, p1);
2585
2588
2589 if (d2d_point_ccw(p0, p1, p2) > 0.0f)
2590 {
2591 d2d_point_scale(&r0, -1.0f);
2592 d2d_point_scale(&r1, -1.0f);
2593 }
2594
2595 d2d_curve_outline_vertex_set(&a[0], p0, p0, p1, p2, r0.x, r0.y, r0.x, r0.y);
2596 d2d_curve_outline_vertex_set(&a[1], p0, p0, p1, p2, -r0.x, -r0.y, -r0.x, -r0.y);
2597 d2d_curve_outline_vertex_set(&a[2], p1, p0, p1, p2, r0.x, r0.y, r1.x, r1.y);
2598 d2d_curve_outline_vertex_set(&a[3], p2, p0, p1, p2, -r1.x, -r1.y, -r1.x, -r1.y);
2599 d2d_curve_outline_vertex_set(&a[4], p2, p0, p1, p2, r1.x, r1.y, r1.x, r1.y);
2600 geometry->outline.arc_count += 5;
2601
2602 d2d_face_set(&f[0], base_idx + 0, base_idx + 1, base_idx + 2);
2603 d2d_face_set(&f[1], base_idx + 2, base_idx + 1, base_idx + 3);
2604 d2d_face_set(&f[2], base_idx + 2, base_idx + 4, base_idx + 3);
2605 geometry->outline.arc_face_count += 3;
2606
2607 return TRUE;
2608}
2609
2611 struct d2d_figure *figure, D2D1_FIGURE_END figure_end)
2612{
2613 const D2D1_POINT_2F *prev, *p0, *p1, *next, *next_prev;
2614 size_t bezier_idx, i, vertex_count;
2615 enum d2d_vertex_type type;
2616
2617 if (!(vertex_count = figure->vertex_count))
2618 return TRUE;
2619
2620 p0 = &figure->vertices[0];
2621 if (figure_end == D2D1_FIGURE_END_CLOSED)
2622 {
2624 return TRUE;
2625
2626 /* In case of a CLOSED path, a join between first and last vertex is
2627 * required. */
2629 prev = &figure->bezier_controls[figure->bezier_control_count - 1];
2630 else
2631 prev = &figure->vertices[vertex_count - 1];
2632 }
2633 else
2634 {
2635 if (!--vertex_count)
2636 return TRUE;
2637 prev = p0;
2638 }
2639
2640 for (i = 0, bezier_idx = 0; i < vertex_count; ++i)
2641 {
2642 if ((type = figure->vertex_types[i]) == D2D_VERTEX_TYPE_NONE)
2643 {
2644 prev = next_prev = &figure->vertices[i];
2645 continue;
2646 }
2647
2648 /* next: tangent along next segment, at p0.
2649 * p1: next vertex. */
2651 {
2652 next_prev = next = &figure->bezier_controls[bezier_idx++];
2653 /* type BEZIER implies i + 1 < figure->vertex_count. */
2654 p1 = &figure->vertices[i + 1];
2655
2656 if (!d2d_geometry_outline_add_bezier_segment(geometry, p0, next, p1))
2657 {
2658 ERR("Failed to add bezier segment.\n");
2659 return FALSE;
2660 }
2661 }
2662 else
2663 {
2664 if (i + 1 == figure->vertex_count)
2665 next = p1 = &figure->vertices[0];
2666 else
2667 next = p1 = &figure->vertices[i + 1];
2668 next_prev = p0;
2669
2670 if (!d2d_geometry_outline_add_line_segment(geometry, p0, p1))
2671 {
2672 ERR("Failed to add line segment.\n");
2673 return FALSE;
2674 }
2675 }
2676
2677 if (i || figure_end == D2D1_FIGURE_END_CLOSED)
2678 {
2679 D2D1_POINT_2F q_next, q_prev;
2680
2681 d2d_point_subtract(&q_prev, prev, p0);
2682 d2d_point_subtract(&q_next, next, p0);
2683
2684 d2d_point_normalise(&q_prev);
2685 d2d_point_normalise(&q_next);
2686
2687 if (!d2d_geometry_outline_add_join(geometry, &q_prev, p0, &q_next))
2688 {
2689 ERR("Failed to add join.\n");
2690 return FALSE;
2691 }
2692 }
2693
2694 p0 = p1;
2695 prev = next_prev;
2696 }
2697
2698 return TRUE;
2699}
2700
2702 const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2)
2703{
2704 struct d2d_curve_vertex *a;
2705
2706 if (!d2d_array_reserve((void **)&geometry->fill.arc_vertices, &geometry->fill.arc_vertices_size,
2707 geometry->fill.arc_vertex_count + 3, sizeof(*geometry->fill.arc_vertices)))
2708 return FALSE;
2709
2710 a = &geometry->fill.arc_vertices[geometry->fill.arc_vertex_count];
2711 d2d_curve_vertex_set(&a[0], p0, 0.0f, 1.0f, -1.0f);
2712 d2d_curve_vertex_set(&a[1], p1, 1.0f, 1.0f, -1.0f);
2713 d2d_curve_vertex_set(&a[2], p2, 1.0f, 0.0f, -1.0f);
2714 geometry->fill.arc_vertex_count += 3;
2715
2716 return TRUE;
2717}
2718
2719static void d2d_geometry_cleanup(struct d2d_geometry *geometry)
2720{
2721 free(geometry->outline.arc_faces);
2722 free(geometry->outline.arcs);
2723 free(geometry->outline.bezier_faces);
2724 free(geometry->outline.beziers);
2725 free(geometry->outline.faces);
2726 free(geometry->outline.vertices);
2727 free(geometry->fill.arc_vertices);
2728 free(geometry->fill.bezier_vertices);
2729 free(geometry->fill.faces);
2730 free(geometry->fill.vertices);
2731 ID2D1Factory_Release(geometry->factory);
2732}
2733
2735 const D2D1_MATRIX_3X2_F *transform, const struct ID2D1GeometryVtbl *vtbl)
2736{
2737 geometry->ID2D1Geometry_iface.lpVtbl = vtbl;
2738 geometry->refcount = 1;
2739 ID2D1Factory_AddRef(geometry->factory = factory);
2740 geometry->transform = *transform;
2741}
2742
2744{
2745 return CONTAINING_RECORD(iface, struct d2d_geometry, u.path.ID2D1GeometrySink_iface);
2746}
2747
2749{
2750 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2751
2752 if (IsEqualGUID(iid, &IID_ID2D1GeometrySink)
2753 || IsEqualGUID(iid, &IID_ID2D1SimplifiedGeometrySink)
2754 || IsEqualGUID(iid, &IID_IUnknown))
2755 {
2756 ID2D1GeometrySink_AddRef(iface);
2757 *out = iface;
2758 return S_OK;
2759 }
2760
2761 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
2762
2763 *out = NULL;
2764 return E_NOINTERFACE;
2765}
2766
2768{
2769 struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
2770
2771 TRACE("iface %p.\n", iface);
2772
2773 return ID2D1Geometry_AddRef(&geometry->ID2D1Geometry_iface);
2774}
2775
2777{
2778 struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
2779
2780 TRACE("iface %p.\n", iface);
2781
2782 return ID2D1Geometry_Release(&geometry->ID2D1Geometry_iface);
2783}
2784
2786{
2787 struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
2788
2789 TRACE("iface %p, mode %#x.\n", iface, mode);
2790
2791 if (geometry->u.path.state == D2D_GEOMETRY_STATE_CLOSED)
2792 return;
2793 geometry->u.path.fill_mode = mode;
2794}
2795
2797{
2798 TRACE("iface %p, flags %#x.\n", iface, flags);
2799
2801 FIXME("Ignoring flags %#x.\n", flags);
2802}
2803
2805 D2D1_POINT_2F start_point, D2D1_FIGURE_BEGIN figure_begin)
2806{
2807 struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
2808 struct d2d_figure *figure;
2809
2810 TRACE("iface %p, start_point %s, figure_begin %#x.\n",
2811 iface, debug_d2d_point_2f(&start_point), figure_begin);
2812
2813 if (geometry->u.path.state != D2D_GEOMETRY_STATE_OPEN)
2814 {
2815 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
2816 return;
2817 }
2818
2819 if (!d2d_path_geometry_add_figure(geometry))
2820 {
2821 ERR("Failed to add figure.\n");
2822 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
2823 return;
2824 }
2825
2826 figure = &geometry->u.path.figures[geometry->u.path.figure_count - 1];
2827 if (figure_begin == D2D1_FIGURE_BEGIN_HOLLOW)
2828 figure->flags |= D2D_FIGURE_FLAG_HOLLOW;
2829
2830 if (!d2d_figure_add_vertex(figure, start_point))
2831 {
2832 ERR("Failed to add vertex.\n");
2833 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
2834 return;
2835 }
2836
2837 geometry->u.path.state = D2D_GEOMETRY_STATE_FIGURE;
2838}
2839
2842{
2843 struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
2844 struct d2d_figure *figure = &geometry->u.path.figures[geometry->u.path.figure_count - 1];
2845 unsigned int i;
2846
2847 TRACE("iface %p, points %p, count %u.\n", iface, points, count);
2848
2849 if (geometry->u.path.state != D2D_GEOMETRY_STATE_FIGURE)
2850 {
2851 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
2852 return;
2853 }
2854
2855 for (i = 0; i < count; ++i)
2856 {
2857 figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_LINE;
2858 if (!d2d_figure_add_vertex(figure, points[i]))
2859 {
2860 ERR("Failed to add vertex.\n");
2861 return;
2862 }
2863 }
2864
2865 geometry->u.path.segment_count += count;
2866}
2867
2869 const D2D1_BEZIER_SEGMENT *beziers, UINT32 count)
2870{
2871 struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
2872 struct d2d_figure *figure = &geometry->u.path.figures[geometry->u.path.figure_count - 1];
2874 unsigned int i;
2875
2876 TRACE("iface %p, beziers %p, count %u.\n", iface, beziers, count);
2877
2878 if (geometry->u.path.state != D2D_GEOMETRY_STATE_FIGURE)
2879 {
2880 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
2881 return;
2882 }
2883
2884 for (i = 0; i < count; ++i)
2885 {
2886 D2D1_RECT_F bezier_bounds;
2887
2888 if (!d2d_figure_add_original_bezier_controls(figure, 1, &beziers[i].point1)
2889 || !d2d_figure_add_original_bezier_controls(figure, 1, &beziers[i].point2))
2890 {
2891 ERR("Failed to add cubic Bézier controls.\n");
2892 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
2893 return;
2894 }
2895
2896 /* FIXME: This tries to approximate a cubic Bézier with a quadratic one. */
2897 p.x = (beziers[i].point1.x + beziers[i].point2.x) * 0.75f;
2898 p.y = (beziers[i].point1.y + beziers[i].point2.y) * 0.75f;
2899 p.x -= (figure->vertices[figure->vertex_count - 1].x + beziers[i].point3.x) * 0.25f;
2900 p.y -= (figure->vertices[figure->vertex_count - 1].y + beziers[i].point3.y) * 0.25f;
2901 figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_BEZIER;
2902
2903 d2d_rect_get_bezier_bounds(&bezier_bounds, &figure->vertices[figure->vertex_count - 1],
2904 &p, &beziers[i].point3);
2905
2906 if (!d2d_figure_add_bezier_controls(figure, 1, &p))
2907 {
2908 ERR("Failed to add bezier control.\n");
2909 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
2910 return;
2911 }
2912
2913 if (!d2d_figure_add_vertex(figure, beziers[i].point3))
2914 {
2915 ERR("Failed to add bezier vertex.\n");
2916 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
2917 return;
2918 }
2919
2920 d2d_rect_union(&figure->bounds, &bezier_bounds);
2921 }
2922
2923 geometry->u.path.segment_count += count;
2924}
2925
2927{
2928 struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
2929 struct d2d_figure *figure;
2930
2931 TRACE("iface %p, figure_end %#x.\n", iface, figure_end);
2932
2933 if (geometry->u.path.state != D2D_GEOMETRY_STATE_FIGURE)
2934 {
2935 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
2936 return;
2937 }
2938
2939 figure = &geometry->u.path.figures[geometry->u.path.figure_count - 1];
2940 if (memcmp(&figure->vertices[0], &figure->vertices[figure->vertex_count - 1], sizeof(*figure->vertices)))
2941 figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_LINE;
2942 else
2943 figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_END;
2944 if (figure_end == D2D1_FIGURE_END_CLOSED)
2945 {
2946 ++geometry->u.path.segment_count;
2947 figure->flags |= D2D_FIGURE_FLAG_CLOSED;
2948 }
2949
2950 if (!d2d_geometry_add_figure_outline(geometry, figure, figure_end))
2951 {
2952 ERR("Failed to add figure outline.\n");
2953 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
2954 return;
2955 }
2956
2957 geometry->u.path.state = D2D_GEOMETRY_STATE_OPEN;
2958}
2959
2961{
2962 size_t i;
2963
2964 if (!geometry->u.path.figures)
2965 return;
2966
2967 for (i = 0; i < geometry->u.path.figure_count; ++i)
2968 {
2969 free(geometry->u.path.figures[i].original_bezier_controls);
2970 free(geometry->u.path.figures[i].bezier_controls);
2971 free(geometry->u.path.figures[i].vertices);
2972 }
2973 free(geometry->u.path.figures);
2974 geometry->u.path.figures = NULL;
2975 geometry->u.path.figures_size = 0;
2976}
2977
2979{
2980 if (next)
2981 {
2982 ++idx->vertex_idx;
2983 ++idx->control_idx;
2984 }
2985
2986 for (; idx->figure_idx < geometry->u.path.figure_count; ++idx->figure_idx, idx->vertex_idx = idx->control_idx = 0)
2987 {
2988 struct d2d_figure *figure = &geometry->u.path.figures[idx->figure_idx];
2989
2990 if (!figure->bezier_control_count || figure->flags & D2D_FIGURE_FLAG_HOLLOW)
2991 continue;
2992
2993 for (; idx->vertex_idx < figure->vertex_count; ++idx->vertex_idx)
2994 {
2995 if (d2d_vertex_type_is_bezier(figure->vertex_types[idx->vertex_idx]))
2996 return TRUE;
2997 }
2998 }
2999
3000 return FALSE;
3001}
3002
3004{
3005 memset(idx, 0, sizeof(*idx));
3006
3008}
3009
3011{
3012 return d2d_geometry_get_bezier_segment_idx(geometry, idx, TRUE);
3013}
3014
3016 const struct d2d_segment_idx *idx_p, const struct d2d_segment_idx *idx_q)
3017{
3018 const D2D1_POINT_2F *a[3], *b[3], *p[2], *q;
3019 const struct d2d_figure *figure;
3020 D2D1_POINT_2F v_q[3], v_p, v_qp;
3021 unsigned int i, j, score;
3022 float det, t;
3023
3024 figure = &geometry->u.path.figures[idx_p->figure_idx];
3025 a[0] = &figure->vertices[idx_p->vertex_idx];
3026 a[1] = &figure->bezier_controls[idx_p->control_idx];
3027 a[2] = &figure->vertices[idx_p->vertex_idx + 1];
3028
3029 figure = &geometry->u.path.figures[idx_q->figure_idx];
3030 b[0] = &figure->vertices[idx_q->vertex_idx];
3031 b[1] = &figure->bezier_controls[idx_q->control_idx];
3032 b[2] = &figure->vertices[idx_q->vertex_idx + 1];
3033
3034 if (d2d_point_ccw(a[0], a[1], a[2]) == 0.0f || d2d_point_ccw(b[0], b[1], b[2]) == 0.0f)
3035 return FALSE;
3036
3037 d2d_point_subtract(&v_q[0], b[1], b[0]);
3038 d2d_point_subtract(&v_q[1], b[2], b[0]);
3039 d2d_point_subtract(&v_q[2], b[1], b[2]);
3040
3041 /* Check for intersections between the edges. Strictly speaking we'd only
3042 * need to check 8 of the 9 possible intersections, since if there's any
3043 * intersection there has to be a second intersection as well. */
3044 for (i = 0; i < 3; ++i)
3045 {
3046 d2d_point_subtract(&v_p, a[(i & 1) + 1], a[i & 2]);
3047 for (j = 0; j < 3; ++j)
3048 {
3049 det = v_p.x * v_q[j].y - v_p.y * v_q[j].x;
3050 if (det == 0.0f)
3051 continue;
3052
3053 d2d_point_subtract(&v_qp, a[i & 2], b[j & 2]);
3054 t = (v_q[j].x * v_qp.y - v_q[j].y * v_qp.x) / det;
3055 if (t <= 0.0f || t >= 1.0f)
3056 continue;
3057
3058 t = (v_p.x * v_qp.y - v_p.y * v_qp.x) / det;
3059 if (t <= 0.0f || t >= 1.0f)
3060 continue;
3061
3062 return TRUE;
3063 }
3064 }
3065
3066 /* Check if one triangle is contained within the other. */
3067 for (j = 0, score = 0, q = a[1], p[0] = b[2]; j < 3; ++j)
3068 {
3069 p[1] = b[j];
3070 d2d_point_subtract(&v_p, p[1], p[0]);
3071 d2d_point_subtract(&v_qp, q, p[0]);
3072
3073 if ((q->y < p[0]->y) != (q->y < p[1]->y) && v_qp.x < v_p.x * (v_qp.y / v_p.y))
3074 ++score;
3075
3076 p[0] = p[1];
3077 }
3078
3079 if (score & 1)
3080 return TRUE;
3081
3082 for (j = 0, score = 0, q = b[1], p[0] = a[2]; j < 3; ++j)
3083 {
3084 p[1] = a[j];
3085 d2d_point_subtract(&v_p, p[1], p[0]);
3086 d2d_point_subtract(&v_qp, q, p[0]);
3087
3088 if ((q->y < p[0]->y) != (q->y < p[1]->y) && v_qp.x < v_p.x * (v_qp.y / v_p.y))
3089 ++score;
3090
3091 p[0] = p[1];
3092 }
3093
3094 return score & 1;
3095}
3096
3097static float d2d_geometry_bezier_ccw(struct d2d_geometry *geometry, const struct d2d_segment_idx *idx)
3098{
3099 const struct d2d_figure *figure = &geometry->u.path.figures[idx->figure_idx];
3100 size_t next = idx->vertex_idx + 1;
3101
3102 return d2d_point_ccw(&figure->vertices[idx->vertex_idx],
3103 &figure->bezier_controls[idx->control_idx], &figure->vertices[next]);
3104}
3105
3106static BOOL d2d_geometry_split_bezier(struct d2d_geometry *geometry, const struct d2d_segment_idx *idx)
3107{
3108 const D2D1_POINT_2F *p[3];
3109 struct d2d_figure *figure;
3110 D2D1_POINT_2F q[3];
3111 size_t next;
3112
3113 figure = &geometry->u.path.figures[idx->figure_idx];
3114 p[0] = &figure->vertices[idx->vertex_idx];
3115 p[1] = &figure->bezier_controls[idx->control_idx];
3116 next = idx->vertex_idx + 1;
3117 p[2] = &figure->vertices[next];
3118
3119 d2d_point_lerp(&q[0], p[0], p[1], 0.5f);
3120 d2d_point_lerp(&q[1], p[1], p[2], 0.5f);
3121 d2d_point_lerp(&q[2], &q[0], &q[1], 0.5f);
3122
3123 figure->bezier_controls[idx->control_idx] = q[0];
3124 if (!(d2d_figure_insert_bezier_controls(figure, idx->control_idx + 1, 1, &q[1])))
3125 return FALSE;
3126 if (!(d2d_figure_insert_vertex(figure, idx->vertex_idx + 1, q[2])))
3127 return FALSE;
3128 figure->vertex_types[idx->vertex_idx + 1] = D2D_VERTEX_TYPE_SPLIT_BEZIER;
3129
3130 return TRUE;
3131}
3132
3134{
3135 struct d2d_segment_idx idx_p, idx_q;
3136 struct d2d_curve_vertex *b;
3137 const D2D1_POINT_2F *p[3];
3138 struct d2d_figure *figure;
3139 size_t bezier_idx, i;
3140
3141 if (!d2d_geometry_get_first_bezier_segment_idx(geometry, &idx_p))
3142 return S_OK;
3143
3144 /* Split overlapping bezier control triangles. */
3145 while (d2d_geometry_get_next_bezier_segment_idx(geometry, &idx_p))
3146 {
3148 while (idx_q.figure_idx < idx_p.figure_idx || idx_q.vertex_idx < idx_p.vertex_idx)
3149 {
3150 while (d2d_geometry_check_bezier_overlap(geometry, &idx_p, &idx_q))
3151 {
3152 if (fabsf(d2d_geometry_bezier_ccw(geometry, &idx_q)) > fabsf(d2d_geometry_bezier_ccw(geometry, &idx_p)))
3153 {
3154 if (!d2d_geometry_split_bezier(geometry, &idx_q))
3155 return E_OUTOFMEMORY;
3156 if (idx_p.figure_idx == idx_q.figure_idx)
3157 {
3158 ++idx_p.vertex_idx;
3159 ++idx_p.control_idx;
3160 }
3161 }
3162 else
3163 {
3164 if (!d2d_geometry_split_bezier(geometry, &idx_p))
3165 return E_OUTOFMEMORY;
3166 }
3167 }
3169 }
3170 }
3171
3172 for (i = 0; i < geometry->u.path.figure_count; ++i)
3173 {
3174 if (geometry->u.path.figures[i].flags & D2D_FIGURE_FLAG_HOLLOW)
3175 continue;
3176 geometry->fill.bezier_vertex_count += 3 * geometry->u.path.figures[i].bezier_control_count;
3177 }
3178
3179 if (!(geometry->fill.bezier_vertices = calloc(geometry->fill.bezier_vertex_count,
3180 sizeof(*geometry->fill.bezier_vertices))))
3181 {
3182 ERR("Failed to allocate bezier vertices array.\n");
3183 geometry->fill.bezier_vertex_count = 0;
3184 return E_OUTOFMEMORY;
3185 }
3186
3187 bezier_idx = 0;
3189 for (;;)
3190 {
3191 float sign = -1.0f;
3192
3193 figure = &geometry->u.path.figures[idx_p.figure_idx];
3194 p[0] = &figure->vertices[idx_p.vertex_idx];
3195 p[1] = &figure->bezier_controls[idx_p.control_idx];
3196
3197 i = idx_p.vertex_idx + 1;
3198 if (d2d_path_geometry_point_inside(geometry, p[1], FALSE))
3199 {
3200 sign = 1.0f;
3201 d2d_figure_insert_vertex(figure, i, *p[1]);
3202 /* Inserting a vertex potentially invalidates p[0]. */
3203 p[0] = &figure->vertices[idx_p.vertex_idx];
3204 ++i;
3205 }
3206
3207 if (i == figure->vertex_count)
3208 i = 0;
3209 p[2] = &figure->vertices[i];
3210
3211 b = &geometry->fill.bezier_vertices[bezier_idx * 3];
3212 d2d_curve_vertex_set(&b[0], p[0], 0.0f, 0.0f, sign);
3213 d2d_curve_vertex_set(&b[1], p[1], 0.5f, 0.0f, sign);
3214 d2d_curve_vertex_set(&b[2], p[2], 1.0f, 1.0f, sign);
3215
3216 if (!d2d_geometry_get_next_bezier_segment_idx(geometry, &idx_p))
3217 break;
3218 ++bezier_idx;
3219 }
3220
3221 return S_OK;
3222}
3223
3225{
3226 struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
3227 HRESULT hr = E_FAIL;
3228
3229 TRACE("iface %p.\n", iface);
3230
3231 if (geometry->u.path.state != D2D_GEOMETRY_STATE_OPEN)
3232 {
3233 if (geometry->u.path.state != D2D_GEOMETRY_STATE_CLOSED)
3234 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
3235 return D2DERR_WRONG_STATE;
3236 }
3237 geometry->u.path.state = D2D_GEOMETRY_STATE_CLOSED;
3238
3239 if (!d2d_geometry_intersect_self(geometry))
3240 goto done;
3241 if (FAILED(hr = d2d_geometry_resolve_beziers(geometry)))
3242 goto done;
3243 if (FAILED(hr = d2d_path_geometry_triangulate(geometry)))
3244 goto done;
3245
3246done:
3247 if (FAILED(hr))
3248 {
3249 free(geometry->fill.bezier_vertices);
3250 geometry->fill.bezier_vertices = NULL;
3251 geometry->fill.bezier_vertex_count = 0;
3253 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
3254 }
3255 return hr;
3256}
3257
3259{
3260 TRACE("iface %p, point %s.\n", iface, debug_d2d_point_2f(&point));
3261
3263}
3264
3266{
3267 TRACE("iface %p, bezier %p.\n", iface, bezier);
3268
3269 d2d_geometry_sink_AddBeziers(iface, bezier, 1);
3270}
3271
3273 const D2D1_QUADRATIC_BEZIER_SEGMENT *bezier)
3274{
3275 TRACE("iface %p, bezier %p.\n", iface, bezier);
3276
3277 ID2D1GeometrySink_AddQuadraticBeziers(iface, bezier, 1);
3278}
3279
3282{
3283 struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
3284 struct d2d_figure *figure = &geometry->u.path.figures[geometry->u.path.figure_count - 1];
3285 unsigned int i;
3286
3287 TRACE("iface %p, beziers %p, bezier_count %u.\n", iface, beziers, bezier_count);
3288
3289 if (geometry->u.path.state != D2D_GEOMETRY_STATE_FIGURE)
3290 {
3291 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
3292 return;
3293 }
3294
3295 for (i = 0; i < bezier_count; ++i)
3296 {
3297 D2D1_RECT_F bezier_bounds;
3298 D2D1_POINT_2F p[2];
3299
3300 /* Construct a cubic curve. */
3301 d2d_point_lerp(&p[0], &figure->vertices[figure->vertex_count - 1], &beziers[i].point1, 2.0f / 3.0f);
3302 d2d_point_lerp(&p[1], &beziers[i].point2, &beziers[i].point1, 2.0f / 3.0f);
3304 {
3305 ERR("Failed to add cubic Bézier controls.\n");
3306 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
3307 return;
3308 }
3309
3310 d2d_rect_get_bezier_bounds(&bezier_bounds, &figure->vertices[figure->vertex_count - 1],
3311 &beziers[i].point1, &beziers[i].point2);
3312
3313 figure->vertex_types[figure->vertex_count - 1] = D2D_VERTEX_TYPE_BEZIER;
3314 if (!d2d_figure_add_bezier_controls(figure, 1, &beziers[i].point1))
3315 {
3316 ERR("Failed to add bezier.\n");
3317 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
3318 return;
3319 }
3320
3321 if (!d2d_figure_add_vertex(figure, beziers[i].point2))
3322 {
3323 ERR("Failed to add bezier vertex.\n");
3324 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
3325 return;
3326 }
3327
3328 d2d_rect_union(&figure->bounds, &bezier_bounds);
3329 }
3330
3331 geometry->u.path.segment_count += bezier_count;
3332}
3333
3335{
3336 struct d2d_geometry *geometry = impl_from_ID2D1GeometrySink(iface);
3337
3338 FIXME("iface %p, arc %p stub!\n", iface, arc);
3339
3340 if (geometry->u.path.state != D2D_GEOMETRY_STATE_FIGURE)
3341 {
3342 geometry->u.path.state = D2D_GEOMETRY_STATE_ERROR;
3343 return;
3344 }
3345
3346 if (!d2d_figure_add_vertex(&geometry->u.path.figures[geometry->u.path.figure_count - 1], arc->point))
3347 {
3348 ERR("Failed to add vertex.\n");
3349 return;
3350 }
3351
3352 ++geometry->u.path.segment_count;
3353}
3354
3355static const struct ID2D1GeometrySinkVtbl d2d_geometry_sink_vtbl =
3356{
3372};
3373
3375{
3376 return CONTAINING_RECORD(iface, struct d2d_geometry, ID2D1Geometry_iface);
3377}
3378
3380{
3381 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
3382
3383 if (IsEqualGUID(iid, &IID_ID2D1PathGeometry1)
3384 || IsEqualGUID(iid, &IID_ID2D1PathGeometry)
3385 || IsEqualGUID(iid, &IID_ID2D1Geometry)
3386 || IsEqualGUID(iid, &IID_ID2D1Resource)
3387 || IsEqualGUID(iid, &IID_IUnknown))
3388 {
3389 ID2D1PathGeometry1_AddRef(iface);
3390 *out = iface;
3391 return S_OK;
3392 }
3393
3394 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
3395
3396 *out = NULL;
3397 return E_NOINTERFACE;
3398}
3399
3401{
3402 struct d2d_geometry *geometry = impl_from_ID2D1PathGeometry1(iface);
3404
3405 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
3406
3407 return refcount;
3408}
3409
3411{
3412 struct d2d_geometry *geometry = impl_from_ID2D1PathGeometry1(iface);
3414
3415 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
3416
3417 if (!refcount)
3418 {
3420 d2d_geometry_cleanup(geometry);
3421 free(geometry);
3422 }
3423
3424 return refcount;
3425}
3426
3428{
3429 struct d2d_geometry *geometry = impl_from_ID2D1PathGeometry1(iface);
3430
3431 TRACE("iface %p, factory %p.\n", iface, factory);
3432
3433 ID2D1Factory_AddRef(*factory = geometry->factory);
3434}
3435
3438{
3439 struct d2d_geometry *geometry = impl_from_ID2D1PathGeometry1(iface);
3440 size_t i;
3441
3442 TRACE("iface %p, transform %p, bounds %p.\n", iface, transform, bounds);
3443
3444 if (geometry->u.path.state != D2D_GEOMETRY_STATE_CLOSED)
3445 return D2DERR_WRONG_STATE;
3446
3447 bounds->left = FLT_MAX;
3448 bounds->top = FLT_MAX;
3449 bounds->right = -FLT_MAX;
3450 bounds->bottom = -FLT_MAX;
3451
3452 if (!transform)
3453 {
3454 if (geometry->u.path.bounds.left > geometry->u.path.bounds.right
3455 && !isinf(geometry->u.path.bounds.left))
3456 {
3457 for (i = 0; i < geometry->u.path.figure_count; ++i)
3458 {
3459 if (geometry->u.path.figures[i].flags & D2D_FIGURE_FLAG_HOLLOW)
3460 continue;
3461 d2d_rect_union(&geometry->u.path.bounds, &geometry->u.path.figures[i].bounds);
3462 }
3463 if (geometry->u.path.bounds.left > geometry->u.path.bounds.right)
3464 {
3465 geometry->u.path.bounds.left = INFINITY;
3466 geometry->u.path.bounds.right = FLT_MAX;
3467 geometry->u.path.bounds.top = INFINITY;
3468 geometry->u.path.bounds.bottom = FLT_MAX;
3469 }
3470 }
3471
3472 *bounds = geometry->u.path.bounds;
3473 return S_OK;
3474 }
3475
3476 for (i = 0; i < geometry->u.path.figure_count; ++i)
3477 {
3478 const struct d2d_figure *figure = &geometry->u.path.figures[i];
3480 D2D1_RECT_F bezier_bounds;
3481 D2D1_POINT_2F p, p1, p2;
3482 size_t j, bezier_idx;
3483
3484 if (figure->flags & D2D_FIGURE_FLAG_HOLLOW)
3485 continue;
3486
3487 for (j = 0; j < figure->vertex_count; ++j)
3488 {
3489 if (figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE)
3490 continue;
3491
3492 p = figure->vertices[j];
3493 type = figure->vertex_types[j];
3496 break;
3497 }
3498
3499 for (bezier_idx = 0, ++j; j < figure->vertex_count; ++j)
3500 {
3501 enum d2d_vertex_type next_type;
3502
3503 if ((next_type = figure->vertex_types[j]) == D2D_VERTEX_TYPE_NONE
3504 || d2d_vertex_type_is_split_bezier(next_type))
3505 continue;
3506
3507 switch (type)
3508 {
3510 p = figure->vertices[j];
3513 break;
3514
3516 /* FIXME: This attempts to approximate a cubic Bézier with
3517 * a quadratic one. */
3518 p1 = figure->original_bezier_controls[bezier_idx++];
3519 d2d_point_transform(&p1, transform, p1.x, p1.y);
3520 p2 = figure->original_bezier_controls[bezier_idx++];
3521 d2d_point_transform(&p2, transform, p2.x, p2.y);
3522 p1.x = (p1.x + p2.x) * 0.75f;
3523 p1.y = (p1.y + p2.y) * 0.75f;
3524 p2 = figure->vertices[j];
3525 d2d_point_transform(&p2, transform, p2.x, p2.y);
3526 p1.x -= (p.x + p2.x) * 0.25f;
3527 p1.y -= (p.y + p2.y) * 0.25f;
3528
3529 d2d_rect_get_bezier_bounds(&bezier_bounds, &p, &p1, &p2);
3530 d2d_rect_union(bounds, &bezier_bounds);
3531 p = p2;
3532 break;
3533
3534 default:
3535 FIXME("Unhandled vertex type %#x.\n", type);
3536 p = figure->vertices[j];
3539 break;
3540 }
3541
3542 type = next_type;
3543 }
3544 }
3545
3546 if (bounds->left > bounds->right)
3547 {
3548 bounds->left = INFINITY;
3549 bounds->right = FLT_MAX;
3550 bounds->top = INFINITY;
3552 }
3553
3554 return S_OK;
3555}
3556
3558 ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_RECT_F *bounds)
3559{
3560 FIXME("iface %p, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, bounds %p stub!\n",
3561 iface, stroke_width, stroke_style, transform, tolerance, bounds);
3562
3563 return E_NOTIMPL;
3564}
3565
3567 D2D1_POINT_2F point, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform,
3568 float tolerance, BOOL *contains)
3569{
3570 struct d2d_geometry *geometry = impl_from_ID2D1PathGeometry1(iface);
3572 unsigned int i, j, bezier_idx;
3574 D2D1_POINT_2F p, p1;
3575
3576 TRACE("iface %p, point %s, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, contains %p.\n",
3577 iface, debug_d2d_point_2f(&point), stroke_width, stroke_style, transform, tolerance, contains);
3578
3579 if (stroke_style)
3580 FIXME("Ignoring stroke style %p.\n", stroke_style);
3581
3582 if (!transform)
3584
3585 if (tolerance <= 0.0f)
3586 tolerance = D2D1_DEFAULT_FLATTENING_TOLERANCE;
3587
3588 *contains = FALSE;
3589 for (i = 0; i < geometry->u.path.figure_count; ++i)
3590 {
3591 const struct d2d_figure *figure = &geometry->u.path.figures[i];
3592
3593 for (j = 0; j < figure->vertex_count; ++j)
3594 {
3595 if (figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE)
3596 continue;
3597
3598 p = figure->vertices[j];
3599 type = figure->vertex_types[j];
3600 break;
3601 }
3602
3603 for (bezier_idx = 0, ++j; j < figure->vertex_count; ++j)
3604 {
3605 enum d2d_vertex_type next_type;
3606
3607 if ((next_type = figure->vertex_types[j]) == D2D_VERTEX_TYPE_NONE
3608 || d2d_vertex_type_is_split_bezier(next_type))
3609 continue;
3610
3611 switch (type)
3612 {
3614 p1 = figure->vertices[j];
3615 *contains = d2d_point_on_line_segment(&point, &p, &p1, transform, stroke_width * 0.5f, tolerance);
3616 p = p1;
3617 break;
3618
3620 b.point1 = figure->original_bezier_controls[bezier_idx++];
3621 b.point2 = figure->original_bezier_controls[bezier_idx++];
3622 b.point3 = figure->vertices[j];
3623 *contains = d2d_point_on_bezier_segment(&point, &p, &b, transform, stroke_width, tolerance);
3624 p = b.point3;
3625 break;
3626
3627 default:
3628 FIXME("Unhandled vertex type %#x.\n", type);
3629 p = figure->vertices[j];
3630 break;
3631 }
3632 if (*contains)
3633 return S_OK;
3634 type = next_type;
3635 }
3636
3638 {
3639 p1 = figure->vertices[0];
3640 if (figure->flags & D2D_FIGURE_FLAG_CLOSED)
3641 *contains = d2d_point_on_line_segment(&point, &p, &p1, transform, stroke_width * 0.5f, tolerance);
3642 }
3643
3644 if (*contains)
3645 return S_OK;
3646 }
3647
3648 return S_OK;
3649}
3650
3652 D2D1_POINT_2F point, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
3653{
3654 struct d2d_geometry *geometry = impl_from_ID2D1PathGeometry1(iface);
3656
3657 TRACE("iface %p, point %s, transform %p, tolerance %.8e, contains %p.\n",
3658 iface, debug_d2d_point_2f(&point), transform, tolerance, contains);
3659
3660 if (transform)
3661 {
3662 if (!d2d_matrix_invert(&g_i, transform))
3665 }
3666
3667 *contains = !!d2d_path_geometry_point_inside(geometry, &point, FALSE);
3668
3669 TRACE("-> %#x.\n", *contains);
3670
3671 return S_OK;
3672}
3673
3675 ID2D1Geometry *geometry, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_GEOMETRY_RELATION *relation)
3676{
3677 FIXME("iface %p, geometry %p, transform %p, tolerance %.8e, relation %p stub!\n",
3678 iface, geometry, transform, tolerance, relation);
3679
3680 return E_NOTIMPL;
3681}
3682
3684 const D2D1_BEZIER_SEGMENT *b, float tolerance)
3685{
3688 float d;
3689
3690 /* It's certainly possible to calculate the maximum deviation of the
3691 * approximation from the curve, but it's a little involved. Instead, note
3692 * that if the control points were evenly spaced and collinear, p1 would
3693 * be exactly between p0 and p2, and p2 would be exactly between p1 and
3694 * p3. The deviation is a decent enough approximation, and much easier to
3695 * calculate.
3696 *
3697 * p1' = (p0 + p2) / 2
3698 * p2' = (p1 + p3) / 2
3699 * d = ‖p1 - p1'‖₁ + ‖p2 - p2'‖₁ */
3700 d2d_point_lerp(&q, p0, &b->point2, 0.5f);
3701 d2d_point_subtract(&q, &b->point1, &q);
3702 d = fabsf(q.x) + fabsf(q.y);
3703 d2d_point_lerp(&q, &b->point1, &b->point3, 0.5f);
3704 d2d_point_subtract(&q, &b->point2, &q);
3705 d += fabsf(q.x) + fabsf(q.y);
3706 if (d < tolerance)
3707 {
3708 ID2D1SimplifiedGeometrySink_AddLines(sink, &b->point3, 1);
3709 return;
3710 }
3711
3712 d2d_point_lerp(&q, &b->point1, &b->point2, 0.5f);
3713
3714 b1.point3 = b->point3;
3715 d2d_point_lerp(&b1.point2, &b1.point3, &b->point2, 0.5f);
3716 d2d_point_lerp(&b1.point1, &b1.point2, &q, 0.5f);
3717
3718 d2d_point_lerp(&b0.point1, p0, &b->point1, 0.5f);
3719 d2d_point_lerp(&b0.point2, &b0.point1, &q, 0.5f);
3720 d2d_point_lerp(&b0.point3, &b0.point2, &b1.point1, 0.5f);
3721
3722 d2d_geometry_flatten_cubic(sink, p0, &b0, tolerance);
3723 ID2D1SimplifiedGeometrySink_SetSegmentFlags(sink, D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN);
3724 d2d_geometry_flatten_cubic(sink, &b0.point3, &b1, tolerance);
3725 ID2D1SimplifiedGeometrySink_SetSegmentFlags(sink, D2D1_PATH_SEGMENT_NONE);
3726}
3727
3731{
3732 struct d2d_geometry *geometry = impl_from_ID2D1PathGeometry1(iface);
3734 unsigned int i, j, bezier_idx;
3735 D2D1_FIGURE_BEGIN begin;
3739
3740 TRACE("iface %p, option %#x, transform %p, tolerance %.8e, sink %p.\n",
3741 iface, option, transform, tolerance, sink);
3742
3743 ID2D1SimplifiedGeometrySink_SetFillMode(sink, geometry->u.path.fill_mode);
3744 for (i = 0; i < geometry->u.path.figure_count; ++i)
3745 {
3746 const struct d2d_figure *figure = &geometry->u.path.figures[i];
3747
3748 for (j = 0; j < figure->vertex_count; ++j)
3749 {
3750 if (figure->vertex_types[j] == D2D_VERTEX_TYPE_NONE)
3751 continue;
3752
3753 p = figure->vertices[j];
3754 if (transform)
3757 ID2D1SimplifiedGeometrySink_BeginFigure(sink, p, begin);
3758 type = figure->vertex_types[j];
3759 break;
3760 }
3761
3762 for (bezier_idx = 0, ++j; j < figure->vertex_count; ++j)
3763 {
3764 enum d2d_vertex_type next_type;
3765
3766 if ((next_type = figure->vertex_types[j]) == D2D_VERTEX_TYPE_NONE
3767 || d2d_vertex_type_is_split_bezier(next_type))
3768 continue;
3769
3770 switch (type)
3771 {
3773 p = figure->vertices[j];
3774 if (transform)
3776 ID2D1SimplifiedGeometrySink_AddLines(sink, &p, 1);
3777 break;
3778
3780 b.point1 = figure->original_bezier_controls[bezier_idx++];
3781 b.point2 = figure->original_bezier_controls[bezier_idx++];
3782 b.point3 = figure->vertices[j];
3783 if (transform)
3784 {
3785 d2d_point_transform(&b.point1, transform, b.point1.x, b.point1.y);
3786 d2d_point_transform(&b.point2, transform, b.point2.x, b.point2.y);
3787 d2d_point_transform(&b.point3, transform, b.point3.x, b.point3.y);
3788 }
3789
3791 d2d_geometry_flatten_cubic(sink, &p, &b, tolerance);
3792 else
3793 ID2D1SimplifiedGeometrySink_AddBeziers(sink, &b, 1);
3794 p = b.point3;
3795 break;
3796
3797 default:
3798 FIXME("Unhandled vertex type %#x.\n", type);
3799 p = figure->vertices[j];
3800 if (transform)
3802 ID2D1SimplifiedGeometrySink_AddLines(sink, &p, 1);
3803 break;
3804 }
3805
3806 type = next_type;
3807 }
3808
3810 ID2D1SimplifiedGeometrySink_EndFigure(sink, end);
3811 }
3812
3813 return S_OK;
3814}
3815
3817 const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1TessellationSink *sink)
3818{
3819 FIXME("iface %p, transform %p, tolerance %.8e, sink %p stub!\n", iface, transform, tolerance, sink);
3820
3821 return E_NOTIMPL;
3822}
3823
3825 ID2D1Geometry *geometry, D2D1_COMBINE_MODE combine_mode, const D2D1_MATRIX_3X2_F *transform,
3826 float tolerance, ID2D1SimplifiedGeometrySink *sink)
3827{
3828 FIXME("iface %p, geometry %p, combine_mode %#x, transform %p, tolerance %.8e, sink %p stub!\n",
3829 iface, geometry, combine_mode, transform, tolerance, sink);
3830
3831 return E_NOTIMPL;
3832}
3833
3836{
3837 FIXME("iface %p, transform %p, tolerance %.8e, sink %p stub!\n", iface, transform, tolerance, sink);
3838
3839 return E_NOTIMPL;
3840}
3841
3843 const D2D1_MATRIX_3X2_F *transform, float tolerance, float *area)
3844{
3845 FIXME("iface %p, transform %p, tolerance %.8e, area %p stub!\n", iface, transform, tolerance, area);
3846
3847 return E_NOTIMPL;
3848}
3849
3851 const D2D1_MATRIX_3X2_F *transform, float tolerance, float *length)
3852{
3853 FIXME("iface %p, transform %p, tolerance %.8e, length %p stub!\n", iface, transform, tolerance, length);
3854
3855 return E_NOTIMPL;
3856}
3857
3859 const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_POINT_2F *point, D2D1_POINT_2F *tangent)
3860{
3861 FIXME("iface %p, length %.8e, transform %p, tolerance %.8e, point %p, tangent %p stub!\n",
3862 iface, length, transform, tolerance, point, tangent);
3863
3864 return E_NOTIMPL;
3865}
3866
3868 ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance,
3870{
3871 FIXME("iface %p, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, sink %p stub!\n",
3872 iface, stroke_width, stroke_style, transform, tolerance, sink);
3873
3874 return E_NOTIMPL;
3875}
3876
3878{
3879 struct d2d_geometry *geometry = impl_from_ID2D1PathGeometry1(iface);
3880
3881 TRACE("iface %p, sink %p.\n", iface, sink);
3882
3883 if (geometry->u.path.state != D2D_GEOMETRY_STATE_INITIAL)
3884 return D2DERR_WRONG_STATE;
3885
3886 *sink = &geometry->u.path.ID2D1GeometrySink_iface;
3887 ID2D1GeometrySink_AddRef(*sink);
3888
3889 geometry->u.path.state = D2D_GEOMETRY_STATE_OPEN;
3890
3891 return S_OK;
3892}
3893
3895{
3896 FIXME("iface %p, sink %p stub!\n", iface, sink);
3897
3898 return E_NOTIMPL;
3899}
3900
3902{
3903 struct d2d_geometry *geometry = impl_from_ID2D1PathGeometry1(iface);
3904
3905 TRACE("iface %p, count %p.\n", iface, count);
3906
3907 if (geometry->u.path.state != D2D_GEOMETRY_STATE_CLOSED)
3908 return D2DERR_WRONG_STATE;
3909
3910 *count = geometry->u.path.segment_count;
3911
3912 return S_OK;
3913}
3914
3916{
3917 struct d2d_geometry *geometry = impl_from_ID2D1PathGeometry1(iface);
3918
3919 TRACE("iface %p, count %p.\n", iface, count);
3920
3921 if (geometry->u.path.state != D2D_GEOMETRY_STATE_CLOSED)
3922 return D2DERR_WRONG_STATE;
3923
3924 *count = geometry->u.path.figure_count;
3925
3926 return S_OK;
3927}
3928
3930 float length, UINT32 start_segment, const D2D1_MATRIX_3X2_F *transform, float tolerance,
3931 D2D1_POINT_DESCRIPTION *point_desc)
3932{
3933 FIXME("iface %p, length %.8e, start_segment %u, transform %p, tolerance %.8e, point_desc %p.\n",
3934 iface, length, start_segment, transform, tolerance, point_desc);
3935
3936 return E_NOTIMPL;
3937}
3938
3939static const struct ID2D1PathGeometry1Vtbl d2d_path_geometry_vtbl =
3940{
3963};
3964
3966{
3967 d2d_geometry_init(geometry, factory, &identity, (ID2D1GeometryVtbl *)&d2d_path_geometry_vtbl);
3968 geometry->u.path.ID2D1GeometrySink_iface.lpVtbl = &d2d_geometry_sink_vtbl;
3969 geometry->u.path.bounds.left = FLT_MAX;
3970 geometry->u.path.bounds.right = -FLT_MAX;
3971 geometry->u.path.bounds.top = FLT_MAX;
3972 geometry->u.path.bounds.bottom = -FLT_MAX;
3973}
3974
3976{
3977 return CONTAINING_RECORD(iface, struct d2d_geometry, ID2D1Geometry_iface);
3978}
3979
3981 REFIID iid, void **out)
3982{
3983 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
3984
3985 if (IsEqualGUID(iid, &IID_ID2D1EllipseGeometry)
3986 || IsEqualGUID(iid, &IID_ID2D1Geometry)
3987 || IsEqualGUID(iid, &IID_ID2D1Resource)
3988 || IsEqualGUID(iid, &IID_IUnknown))
3989 {
3990 ID2D1EllipseGeometry_AddRef(iface);
3991 *out = iface;
3992 return S_OK;
3993 }
3994
3995 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
3996
3997 *out = NULL;
3998 return E_NOINTERFACE;
3999}
4000
4002{
4003 struct d2d_geometry *geometry = impl_from_ID2D1EllipseGeometry(iface);
4005
4006 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
4007
4008 return refcount;
4009}
4010
4012{
4013 struct d2d_geometry *geometry = impl_from_ID2D1EllipseGeometry(iface);
4015
4016 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
4017
4018 if (!refcount)
4019 {
4020 d2d_geometry_cleanup(geometry);
4021 free(geometry);
4022 }
4023
4024 return refcount;
4025}
4026
4028{
4029 struct d2d_geometry *geometry = impl_from_ID2D1EllipseGeometry(iface);
4030
4031 TRACE("iface %p, factory %p.\n", iface, factory);
4032
4033 ID2D1Factory_AddRef(*factory = geometry->factory);
4034}
4035
4038{
4039 FIXME("iface %p, transform %p, bounds %p stub!\n", iface, transform, bounds);
4040
4041 return E_NOTIMPL;
4042}
4043
4045 float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform,
4046 float tolerance, D2D1_RECT_F *bounds)
4047{
4048 FIXME("iface %p, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, bounds %p stub!\n",
4049 iface, stroke_width, stroke_style, transform, tolerance, bounds);
4050
4051 return E_NOTIMPL;
4052}
4053
4055 D2D1_POINT_2F point, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform,
4056 float tolerance, BOOL *contains)
4057{
4058 FIXME("iface %p, point %s, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, contains %p stub!\n",
4059 iface, debug_d2d_point_2f(&point), stroke_width, stroke_style, transform, tolerance, contains);
4060
4061 return E_NOTIMPL;
4062}
4063
4065 D2D1_POINT_2F point, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
4066{
4067 FIXME("iface %p, point %s, transform %p, tolerance %.8e, contains %p stub!\n",
4068 iface, debug_d2d_point_2f(&point), transform, tolerance, contains);
4069
4070 return E_NOTIMPL;
4071}
4072
4074 ID2D1Geometry *geometry, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_GEOMETRY_RELATION *relation)
4075{
4076 FIXME("iface %p, geometry %p, transform %p, tolerance %.8e, relation %p stub!\n",
4077 iface, geometry, transform, tolerance, relation);
4078
4079 return E_NOTIMPL;
4080}
4081
4085{
4086 FIXME("iface %p, option %#x, transform %p, tolerance %.8e, sink %p stub!\n",
4087 iface, option, transform, tolerance, sink);
4088
4089 return E_NOTIMPL;
4090}
4091
4093 const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1TessellationSink *sink)
4094{
4095 FIXME("iface %p, transform %p, tolerance %.8e, sink %p stub!\n", iface, transform, tolerance, sink);
4096
4097 return E_NOTIMPL;
4098}
4099
4101 ID2D1Geometry *geometry, D2D1_COMBINE_MODE combine_mode, const D2D1_MATRIX_3X2_F *transform,
4102 float tolerance, ID2D1SimplifiedGeometrySink *sink)
4103{
4104 FIXME("iface %p, geometry %p, combine_mode %#x, transform %p, tolerance %.8e, sink %p stub!\n",
4105 iface, geometry, combine_mode, transform, tolerance, sink);
4106
4107 return E_NOTIMPL;
4108}
4109
4112{
4113 FIXME("iface %p, transform %p, tolerance %.8e, sink %p stub!\n", iface, transform, tolerance, sink);
4114
4115 return E_NOTIMPL;
4116}
4117
4119 const D2D1_MATRIX_3X2_F *transform, float tolerance, float *area)
4120{
4121 FIXME("iface %p, transform %p, tolerance %.8e, area %p stub!\n", iface, transform, tolerance, area);
4122
4123 return E_NOTIMPL;
4124}
4125
4127 const D2D1_MATRIX_3X2_F *transform, float tolerance, float *length)
4128{
4129 FIXME("iface %p, transform %p, tolerance %.8e, length %p stub!\n", iface, transform, tolerance, length);
4130
4131 return E_NOTIMPL;
4132}
4133
4135 float length, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_POINT_2F *point,
4136 D2D1_POINT_2F *tangent)
4137{
4138 FIXME("iface %p, length %.8e, transform %p, tolerance %.8e, point %p, tangent %p stub!\n",
4139 iface, length, transform, tolerance, point, tangent);
4140
4141 return E_NOTIMPL;
4142}
4143
4145 ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance,
4147{
4148 FIXME("iface %p, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, sink %p stub!\n",
4149 iface, stroke_width, stroke_style, transform, tolerance, sink);
4150
4151 return E_NOTIMPL;
4152}
4153
4155{
4156 struct d2d_geometry *geometry = impl_from_ID2D1EllipseGeometry(iface);
4157
4158 TRACE("iface %p, ellipse %p.\n", iface, ellipse);
4159
4160 *ellipse = geometry->u.ellipse.ellipse;
4161}
4162
4163static const struct ID2D1EllipseGeometryVtbl d2d_ellipse_geometry_vtbl =
4164{
4183};
4184
4186{
4187 D2D1_POINT_2F *v, v1, v2, v3, v4;
4188 struct d2d_face *f;
4189 float l, r, t, b;
4190
4191 d2d_geometry_init(geometry, factory, &identity, (ID2D1GeometryVtbl *)&d2d_ellipse_geometry_vtbl);
4192 geometry->u.ellipse.ellipse = *ellipse;
4193
4194 if (!(geometry->fill.vertices = malloc(4 * sizeof(*geometry->fill.vertices))))
4195 goto fail;
4196 if (!d2d_array_reserve((void **)&geometry->fill.faces,
4197 &geometry->fill.faces_size, 2, sizeof(*geometry->fill.faces)))
4198 goto fail;
4199
4200 l = ellipse->point.x - ellipse->radiusX;
4201 r = ellipse->point.x + ellipse->radiusX;
4202 t = ellipse->point.y - ellipse->radiusY;
4203 b = ellipse->point.y + ellipse->radiusY;
4204
4205 d2d_point_set(&v1, r, t);
4206 d2d_point_set(&v2, r, b);
4207 d2d_point_set(&v3, l, b);
4208 d2d_point_set(&v4, l, t);
4209
4210 v = geometry->fill.vertices;
4211 d2d_point_set(&v[0], ellipse->point.x, t);
4212 d2d_point_set(&v[1], r, ellipse->point.y);
4213 d2d_point_set(&v[2], ellipse->point.x, b);
4214 d2d_point_set(&v[3], l, ellipse->point.y);
4215 geometry->fill.vertex_count = 4;
4216
4217 f = geometry->fill.faces;
4218 d2d_face_set(&f[0], 0, 3, 2);
4219 d2d_face_set(&f[1], 0, 2, 1);
4220 geometry->fill.face_count = 2;
4221
4222 if (!d2d_geometry_fill_add_arc_triangle(geometry, &v[0], &v1, &v[1]))
4223 goto fail;
4224 if (!d2d_geometry_fill_add_arc_triangle(geometry, &v[1], &v2, &v[2]))
4225 goto fail;
4226 if (!d2d_geometry_fill_add_arc_triangle(geometry, &v[2], &v3, &v[3]))
4227 goto fail;
4228 if (!d2d_geometry_fill_add_arc_triangle(geometry, &v[3], &v4, &v[0]))
4229 goto fail;
4230
4231 if (!d2d_geometry_outline_add_arc_quadrant(geometry, &v[0], &v1, &v[1]))
4232 goto fail;
4233 if (!d2d_geometry_outline_add_arc_quadrant(geometry, &v[1], &v2, &v[2]))
4234 goto fail;
4235 if (!d2d_geometry_outline_add_arc_quadrant(geometry, &v[2], &v3, &v[3]))
4236 goto fail;
4237 if (!d2d_geometry_outline_add_arc_quadrant(geometry, &v[3], &v4, &v[0]))
4238 goto fail;
4239
4240 return S_OK;
4241
4242fail:
4243 d2d_geometry_cleanup(geometry);
4244 return E_OUTOFMEMORY;
4245}
4246
4248{
4249 return CONTAINING_RECORD(iface, struct d2d_geometry, ID2D1Geometry_iface);
4250}
4251
4253 REFIID iid, void **out)
4254{
4255 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
4256
4257 if (IsEqualGUID(iid, &IID_ID2D1RectangleGeometry)
4258 || IsEqualGUID(iid, &IID_ID2D1Geometry)
4259 || IsEqualGUID(iid, &IID_ID2D1Resource)
4260 || IsEqualGUID(iid, &IID_IUnknown))
4261 {
4262 ID2D1RectangleGeometry_AddRef(iface);
4263 *out = iface;
4264 return S_OK;
4265 }
4266
4267 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
4268
4269 *out = NULL;
4270 return E_NOINTERFACE;
4271}
4272
4274{
4275 struct d2d_geometry *geometry = impl_from_ID2D1RectangleGeometry(iface);
4277
4278 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
4279
4280 return refcount;
4281}
4282
4284{
4285 struct d2d_geometry *geometry = impl_from_ID2D1RectangleGeometry(iface);
4287
4288 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
4289
4290 if (!refcount)
4291 {
4292 d2d_geometry_cleanup(geometry);
4293 free(geometry);
4294 }
4295
4296 return refcount;
4297}
4298
4300{
4301 struct d2d_geometry *geometry = impl_from_ID2D1RectangleGeometry(iface);
4302
4303 TRACE("iface %p, factory %p.\n", iface, factory);
4304
4305 ID2D1Factory_AddRef(*factory = geometry->factory);
4306}
4307
4310{
4311 struct d2d_geometry *geometry = impl_from_ID2D1RectangleGeometry(iface);
4314
4315 TRACE("iface %p, transform %p, bounds %p.\n", iface, transform, bounds);
4316
4317 rect = &geometry->u.rectangle.rect;
4318 if (!transform)
4319 {
4320 *bounds = *rect;
4321 return S_OK;
4322 }
4323
4324 bounds->left = FLT_MAX;
4325 bounds->top = FLT_MAX;
4326 bounds->right = -FLT_MAX;
4327 bounds->bottom = -FLT_MAX;
4328
4337
4338 return S_OK;
4339}
4340
4342 float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform,
4343 float tolerance, D2D1_RECT_F *bounds)
4344{
4345 FIXME("iface %p, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, bounds %p stub!\n",
4346 iface, stroke_width, stroke_style, transform, tolerance, bounds);
4347
4348 return E_NOTIMPL;
4349}
4350
4352 D2D1_POINT_2F point, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform,
4353 float tolerance, BOOL *contains)
4354{
4355 const struct d2d_geometry *geometry = impl_from_ID2D1RectangleGeometry(iface);
4356 const D2D1_RECT_F *rect = &geometry->u.rectangle.rect;
4357 unsigned int i;
4358 struct
4359 {
4360 D2D1_POINT_2F s, e;
4361 }
4362 segments[4];
4363
4364 TRACE("iface %p, point %s, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, contains %p.\n",
4365 iface, debug_d2d_point_2f(&point), stroke_width, stroke_style, transform, tolerance, contains);
4366
4367 if (stroke_style)
4368 FIXME("Ignoring stroke style %p.\n", stroke_style);
4369
4370 tolerance = fabsf(tolerance);
4371
4372 if (!transform)
4373 {
4374 D2D1_POINT_2F d, s;
4375
4376 s.x = rect->right - rect->left;
4377 s.y = rect->bottom - rect->top;
4378 d.x = fabsf((rect->right + rect->left) * 0.5f - point.x);
4379 d.y = fabsf((rect->bottom + rect->top) * 0.5f - point.y);
4380
4381 /* Inside test. */
4382 if (d.x <= (s.x - stroke_width) * 0.5f - tolerance && d.y <= (s.y - stroke_width) * 0.5f - tolerance)
4383 {
4384 *contains = FALSE;
4385 return S_OK;
4386 }
4387
4388 if (tolerance == 0.0f)
4389 {
4390 *contains = d.x < (s.x + stroke_width) * 0.5f && d.y < (s.y + stroke_width) * 0.5f;
4391 }
4392 else
4393 {
4394 d.x = max(d.x - (s.x + stroke_width) * 0.5f, 0.0f);
4395 d.y = max(d.y - (s.y + stroke_width) * 0.5f, 0.0f);
4396
4397 *contains = d2d_point_dot(&d, &d) < tolerance * tolerance;
4398 }
4399
4400 return S_OK;
4401 }
4402
4403 stroke_width *= 0.5f;
4404
4405 d2d_point_set(&segments[0].s, rect->left - stroke_width, rect->bottom);
4406 d2d_point_set(&segments[0].e, rect->right + stroke_width, rect->bottom);
4407 d2d_point_set(&segments[1].s, rect->right, rect->bottom + stroke_width);
4408 d2d_point_set(&segments[1].e, rect->right, rect->top - stroke_width);
4409 d2d_point_set(&segments[2].s, rect->right + stroke_width, rect->top);
4410 d2d_point_set(&segments[2].e, rect->left - stroke_width, rect->top);
4411 d2d_point_set(&segments[3].s, rect->left, rect->top - stroke_width);
4412 d2d_point_set(&segments[3].e, rect->left, rect->bottom + stroke_width);
4413
4414 *contains = FALSE;
4415 for (i = 0; i < ARRAY_SIZE(segments); ++i)
4416 {
4417 if (d2d_point_on_line_segment(&point, &segments[i].s, &segments[i].e, transform, stroke_width, tolerance))
4418 {
4419 *contains = TRUE;
4420 break;
4421 }
4422 }
4423
4424 return S_OK;
4425}
4426
4428 D2D1_POINT_2F point, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
4429{
4430 struct d2d_geometry *geometry = impl_from_ID2D1RectangleGeometry(iface);
4431 D2D1_RECT_F *rect = &geometry->u.rectangle.rect;
4432 float dx, dy;
4433
4434 TRACE("iface %p, point %s, transform %p, tolerance %.8e, contains %p.\n",
4435 iface, debug_d2d_point_2f(&point), transform, tolerance, contains);
4436
4437 if (transform)
4438 {
4440
4441 if (!d2d_matrix_invert(&g_i, transform))
4444 }
4445
4446 if (tolerance == 0.0f)
4447 tolerance = D2D1_DEFAULT_FLATTENING_TOLERANCE;
4448
4449 dx = max(fabsf((rect->right + rect->left) / 2.0f - point.x) - (rect->right - rect->left) / 2.0f, 0.0f);
4450 dy = max(fabsf((rect->bottom + rect->top) / 2.0f - point.y) - (rect->bottom - rect->top) / 2.0f, 0.0f);
4451
4452 *contains = tolerance * tolerance > (dx * dx + dy * dy);
4453 return S_OK;
4454}
4455
4457 ID2D1Geometry *geometry, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_GEOMETRY_RELATION *relation)
4458{
4459 FIXME("iface %p, geometry %p, transform %p, tolerance %.8e, relation %p stub!\n",
4460 iface, geometry, transform, tolerance, relation);
4461
4462 return E_NOTIMPL;
4463}
4464
4468{
4469 struct d2d_geometry *geometry = impl_from_ID2D1RectangleGeometry(iface);
4470 D2D1_RECT_F *rect = &geometry->u.rectangle.rect;
4471 D2D1_POINT_2F p[4];
4472 unsigned int i;
4473
4474 TRACE("iface %p, option %#x, transform %p, tolerance %.8e, sink %p.\n",
4475 iface, option, transform, tolerance, sink);
4476
4477 d2d_point_set(&p[0], rect->left, rect->top);
4478 d2d_point_set(&p[1], rect->right, rect->top);
4481
4482 if (transform)
4483 {
4484 for (i = 0; i < ARRAY_SIZE(p); ++i)
4485 {
4486 d2d_point_transform(&p[i], transform, p[i].x, p[i].y);
4487 }
4488 }
4489
4490 ID2D1SimplifiedGeometrySink_SetFillMode(sink, D2D1_FILL_MODE_ALTERNATE);
4491 ID2D1SimplifiedGeometrySink_BeginFigure(sink, p[0], D2D1_FIGURE_BEGIN_FILLED);
4492 ID2D1SimplifiedGeometrySink_AddLines(sink, &p[1], 3);
4493 ID2D1SimplifiedGeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
4494
4495 return S_OK;
4496}
4497
4499 const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1TessellationSink *sink)
4500{
4501 FIXME("iface %p, transform %p, tolerance %.8e, sink %p stub!\n", iface, transform, tolerance, sink);
4502
4503 return E_NOTIMPL;
4504}
4505
4507 ID2D1Geometry *geometry, D2D1_COMBINE_MODE combine_mode, const D2D1_MATRIX_3X2_F *transform,
4508 float tolerance, ID2D1SimplifiedGeometrySink *sink)
4509{
4510 FIXME("iface %p, geometry %p, combine_mode %#x, transform %p, tolerance %.8e, sink %p stub!\n",
4511 iface, geometry, combine_mode, transform, tolerance, sink);
4512
4513 return E_NOTIMPL;
4514}
4515
4518{
4519 FIXME("iface %p, transform %p, tolerance %.8e, sink %p stub!\n", iface, transform, tolerance, sink);
4520
4521 return E_NOTIMPL;
4522}
4523
4525 const D2D1_MATRIX_3X2_F *transform, float tolerance, float *area)
4526{
4527 FIXME("iface %p, transform %p, tolerance %.8e, area %p stub!\n", iface, transform, tolerance, area);
4528
4529 return E_NOTIMPL;
4530}
4531
4533 const D2D1_MATRIX_3X2_F *transform, float tolerance, float *length)
4534{
4535 FIXME("iface %p, transform %p, tolerance %.8e, length %p stub!\n", iface, transform, tolerance, length);
4536
4537 return E_NOTIMPL;
4538}
4539
4541 float length, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_POINT_2F *point,
4542 D2D1_POINT_2F *tangent)
4543{
4544 FIXME("iface %p, length %.8e, transform %p, tolerance %.8e, point %p, tangent %p stub!\n",
4545 iface, length, transform, tolerance, point, tangent);
4546
4547 return E_NOTIMPL;
4548}
4549
4551 ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance,
4553{
4554 FIXME("iface %p, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, sink %p stub!\n",
4555 iface, stroke_width, stroke_style, transform, tolerance, sink);
4556
4557 return E_NOTIMPL;
4558}
4559
4561{
4562 struct d2d_geometry *geometry = impl_from_ID2D1RectangleGeometry(iface);
4563
4564 TRACE("iface %p, rect %p.\n", iface, rect);
4565
4566 *rect = geometry->u.rectangle.rect;
4567}
4568
4569static const struct ID2D1RectangleGeometryVtbl d2d_rectangle_geometry_vtbl =
4570{
4589};
4590
4592{
4593 struct d2d_face *f;
4595 float l, r, t, b;
4596
4597 static const D2D1_POINT_2F prev[] =
4598 {
4599 { 1.0f, 0.0f},
4600 { 0.0f, -1.0f},
4601 {-1.0f, 0.0f},
4602 { 0.0f, 1.0f},
4603 };
4604 static const D2D1_POINT_2F next[] =
4605 {
4606 { 0.0f, 1.0f},
4607 { 1.0f, 0.0f},
4608 { 0.0f, -1.0f},
4609 {-1.0f, 0.0f},
4610 };
4611
4612 d2d_geometry_init(geometry, factory, &identity, (ID2D1GeometryVtbl *)&d2d_rectangle_geometry_vtbl);
4613 geometry->u.rectangle.rect = *rect;
4614
4615 if (!(geometry->fill.vertices = malloc(4 * sizeof(*geometry->fill.vertices))))
4616 goto fail;
4617 if (!d2d_array_reserve((void **)&geometry->fill.faces,
4618 &geometry->fill.faces_size, 2, sizeof(*geometry->fill.faces)))
4619 goto fail;
4620
4621 l = min(rect->left, rect->right);
4622 r = max(rect->left, rect->right);
4623 t = min(rect->top, rect->bottom);
4624 b = max(rect->top, rect->bottom);
4625
4626 v = geometry->fill.vertices;
4627 d2d_point_set(&v[0], l, t);
4628 d2d_point_set(&v[1], l, b);
4629 d2d_point_set(&v[2], r, b);
4630 d2d_point_set(&v[3], r, t);
4631 geometry->fill.vertex_count = 4;
4632
4633 f = geometry->fill.faces;
4634 d2d_face_set(&f[0], 1, 2, 0);
4635 d2d_face_set(&f[1], 0, 2, 3);
4636 geometry->fill.face_count = 2;
4637
4638 if (!d2d_geometry_outline_add_line_segment(geometry, &v[0], &v[1]))
4639 goto fail;
4640 if (!d2d_geometry_outline_add_line_segment(geometry, &v[1], &v[2]))
4641 goto fail;
4642 if (!d2d_geometry_outline_add_line_segment(geometry, &v[2], &v[3]))
4643 goto fail;
4644 if (!d2d_geometry_outline_add_line_segment(geometry, &v[3], &v[0]))
4645 goto fail;
4646
4647 if (!d2d_geometry_outline_add_join(geometry, &prev[0], &v[0], &next[0]))
4648 goto fail;
4649 if (!d2d_geometry_outline_add_join(geometry, &prev[1], &v[1], &next[1]))
4650 goto fail;
4651 if (!d2d_geometry_outline_add_join(geometry, &prev[2], &v[2], &next[2]))
4652 goto fail;
4653 if (!d2d_geometry_outline_add_join(geometry, &prev[3], &v[3], &next[3]))
4654 goto fail;
4655
4656 return S_OK;
4657
4658fail:
4659 d2d_geometry_cleanup(geometry);
4660 return E_OUTOFMEMORY;
4661}
4662
4664{
4665 return CONTAINING_RECORD(iface, struct d2d_geometry, ID2D1Geometry_iface);
4666}
4667
4669 REFIID iid, void **out)
4670{
4671 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
4672
4673 if (IsEqualGUID(iid, &IID_ID2D1RoundedRectangleGeometry)
4674 || IsEqualGUID(iid, &IID_ID2D1Geometry)
4675 || IsEqualGUID(iid, &IID_ID2D1Resource)
4676 || IsEqualGUID(iid, &IID_IUnknown))
4677 {
4678 ID2D1RoundedRectangleGeometry_AddRef(iface);
4679 *out = iface;
4680 return S_OK;
4681 }
4682
4683 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
4684
4685 *out = NULL;
4686 return E_NOINTERFACE;
4687}
4688
4690{
4691 struct d2d_geometry *geometry = impl_from_ID2D1RoundedRectangleGeometry(iface);
4693
4694 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
4695
4696 return refcount;
4697}
4698
4700{
4701 struct d2d_geometry *geometry = impl_from_ID2D1RoundedRectangleGeometry(iface);
4703
4704 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
4705
4706 if (!refcount)
4707 {
4708 d2d_geometry_cleanup(geometry);
4709 free(geometry);
4710 }
4711
4712 return refcount;
4713}
4714
4717{
4718 struct d2d_geometry *geometry = impl_from_ID2D1RoundedRectangleGeometry(iface);
4719
4720 TRACE("iface %p, factory %p.\n", iface, factory);
4721
4722 ID2D1Factory_AddRef(*factory = geometry->factory);
4723}
4724
4727{
4728 FIXME("iface %p, transform %p, bounds %p stub!\n", iface, transform, bounds);
4729
4730 return E_NOTIMPL;
4731}
4732
4734 float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform,
4735 float tolerance, D2D1_RECT_F *bounds)
4736{
4737 FIXME("iface %p, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, bounds %p stub!\n",
4738 iface, stroke_width, stroke_style, transform, tolerance, bounds);
4739
4740 return E_NOTIMPL;
4741}
4742
4744 ID2D1RoundedRectangleGeometry *iface, D2D1_POINT_2F point, float stroke_width,
4745 ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
4746{
4747 FIXME("iface %p, point %s, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, contains %p stub!\n",
4748 iface, debug_d2d_point_2f(&point), stroke_width, stroke_style, transform, tolerance, contains);
4749
4750 return E_NOTIMPL;
4751}
4752
4754 D2D1_POINT_2F point, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
4755{
4756 FIXME("iface %p, point %s, transform %p, tolerance %.8e, contains %p stub!\n",
4757 iface, debug_d2d_point_2f(&point), transform, tolerance, contains);
4758
4759 return E_NOTIMPL;
4760}
4761
4764 const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_GEOMETRY_RELATION *relation)
4765{
4766 FIXME("iface %p, geometry %p, transform %p, tolerance %.8e, relation %p stub!\n",
4767 iface, geometry, transform, tolerance, relation);
4768
4769 return E_NOTIMPL;
4770}
4771
4775{
4776 FIXME("iface %p, option %#x, transform %p, tolerance %.8e, sink %p stub!\n",
4777 iface, option, transform, tolerance, sink);
4778
4779 return E_NOTIMPL;
4780}
4781
4783 const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1TessellationSink *sink)
4784{
4785 FIXME("iface %p, transform %p, tolerance %.8e, sink %p stub!\n", iface, transform, tolerance, sink);
4786
4787 return E_NOTIMPL;
4788}
4789
4791 ID2D1RoundedRectangleGeometry *iface, ID2D1Geometry *geometry, D2D1_COMBINE_MODE combine_mode,
4793{
4794 FIXME("iface %p, geometry %p, combine_mode %#x, transform %p, tolerance %.8e, sink %p stub!\n",
4795 iface, geometry, combine_mode, transform, tolerance, sink);
4796
4797 return E_NOTIMPL;
4798}
4799
4802{
4803 FIXME("iface %p, transform %p, tolerance %.8e, sink %p stub!\n", iface, transform, tolerance, sink);
4804
4805 return E_NOTIMPL;
4806}
4807
4809 const D2D1_MATRIX_3X2_F *transform, float tolerance, float *area)
4810{
4811 FIXME("iface %p, transform %p, tolerance %.8e, area %p stub!\n", iface, transform, tolerance, area);
4812
4813 return E_NOTIMPL;
4814}
4815
4817 const D2D1_MATRIX_3X2_F *transform, float tolerance, float *length)
4818{
4819 FIXME("iface %p, transform %p, tolerance %.8e, length %p stub!\n", iface, transform, tolerance, length);
4820
4821 return E_NOTIMPL;
4822}
4823
4826 float tolerance, D2D1_POINT_2F *point, D2D1_POINT_2F *tangent)
4827{
4828 FIXME("iface %p, length %.8e, transform %p, tolerance %.8e, point %p, tangent %p stub!\n",
4829 iface, length, transform, tolerance, point, tangent);
4830
4831 return E_NOTIMPL;
4832}
4833
4835 float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform,
4836 float tolerance, ID2D1SimplifiedGeometrySink *sink)
4837{
4838 FIXME("iface %p, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, sink %p stub!\n",
4839 iface, stroke_width, stroke_style, transform, tolerance, sink);
4840
4841 return E_NOTIMPL;
4842}
4843
4846{
4847 struct d2d_geometry *geometry = impl_from_ID2D1RoundedRectangleGeometry(iface);
4848
4849 TRACE("iface %p, rounded_rect %p.\n", iface, rounded_rect);
4850
4851 *rounded_rect = geometry->u.rounded_rectangle.rounded_rect;
4852}
4853
4854static const struct ID2D1RoundedRectangleGeometryVtbl d2d_rounded_rectangle_geometry_vtbl =
4855{
4874};
4875
4877 ID2D1Factory *factory, const D2D1_ROUNDED_RECT *rounded_rect)
4878{
4879 D2D1_POINT_2F *v, v1, v2, v3, v4;
4880 struct d2d_face *f;
4881 float l, r, t, b;
4882 float rx, ry;
4883
4884 d2d_geometry_init(geometry, factory, &identity, (ID2D1GeometryVtbl *)&d2d_rounded_rectangle_geometry_vtbl);
4885 geometry->u.rounded_rectangle.rounded_rect = *rounded_rect;
4886
4887 if (!(geometry->fill.vertices = malloc(8 * sizeof(*geometry->fill.vertices))))
4888 goto fail;
4889 if (!d2d_array_reserve((void **)&geometry->fill.faces,
4890 &geometry->fill.faces_size, 6, sizeof(*geometry->fill.faces)))
4891 goto fail;
4892
4893 l = min(rounded_rect->rect.left, rounded_rect->rect.right);
4894 r = max(rounded_rect->rect.left, rounded_rect->rect.right);
4895 t = min(rounded_rect->rect.top, rounded_rect->rect.bottom);
4896 b = max(rounded_rect->rect.top, rounded_rect->rect.bottom);
4897
4898 rx = min(rounded_rect->radiusX, 0.5f * (r - l));
4899 ry = min(rounded_rect->radiusY, 0.5f * (b - t));
4900
4901 d2d_point_set(&v1, r, t);
4902 d2d_point_set(&v2, r, b);
4903 d2d_point_set(&v3, l, b);
4904 d2d_point_set(&v4, l, t);
4905
4906 v = geometry->fill.vertices;
4907 d2d_point_set(&v[0], l + rx, t);
4908 d2d_point_set(&v[1], r - rx, t);
4909 d2d_point_set(&v[2], r, t + ry);
4910 d2d_point_set(&v[3], r, b - ry);
4911 d2d_point_set(&v[4], r - rx, b);
4912 d2d_point_set(&v[5], l + rx, b);
4913 d2d_point_set(&v[6], l, b - ry);
4914 d2d_point_set(&v[7], l, t + ry);
4915 geometry->fill.vertex_count = 8;
4916
4917 f = geometry->fill.faces;
4918 d2d_face_set(&f[0], 0, 7, 6);
4919 d2d_face_set(&f[1], 0, 6, 5);
4920 d2d_face_set(&f[2], 0, 5, 4);
4921 d2d_face_set(&f[3], 0, 4, 1);
4922 d2d_face_set(&f[4], 1, 4, 3);
4923 d2d_face_set(&f[5], 1, 3, 2);
4924 geometry->fill.face_count = 6;
4925
4926 if (!d2d_geometry_fill_add_arc_triangle(geometry, &v[1], &v1, &v[2]))
4927 goto fail;
4928 if (!d2d_geometry_fill_add_arc_triangle(geometry, &v[3], &v2, &v[4]))
4929 goto fail;
4930 if (!d2d_geometry_fill_add_arc_triangle(geometry, &v[5], &v3, &v[6]))
4931 goto fail;
4932 if (!d2d_geometry_fill_add_arc_triangle(geometry, &v[7], &v4, &v[0]))
4933 goto fail;
4934
4935 if (!d2d_geometry_outline_add_line_segment(geometry, &v[0], &v[1]))
4936 goto fail;
4937 if (!d2d_geometry_outline_add_arc_quadrant(geometry, &v[1], &v1, &v[2]))
4938 goto fail;
4939 if (!d2d_geometry_outline_add_line_segment(geometry, &v[2], &v[3]))
4940 goto fail;
4941 if (!d2d_geometry_outline_add_arc_quadrant(geometry, &v[3], &v2, &v[4]))
4942 goto fail;
4943 if (!d2d_geometry_outline_add_line_segment(geometry, &v[4], &v[5]))
4944 goto fail;
4945 if (!d2d_geometry_outline_add_arc_quadrant(geometry, &v[5], &v3, &v[6]))
4946 goto fail;
4947 if (!d2d_geometry_outline_add_line_segment(geometry, &v[6], &v[7]))
4948 goto fail;
4949 if (!d2d_geometry_outline_add_arc_quadrant(geometry, &v[7], &v4, &v[0]))
4950 goto fail;
4951
4952 return S_OK;
4953
4954fail:
4955 d2d_geometry_cleanup(geometry);
4956 return E_OUTOFMEMORY;
4957}
4958
4960{
4961 return CONTAINING_RECORD(iface, struct d2d_geometry, ID2D1Geometry_iface);
4962}
4963
4965 REFIID iid, void **out)
4966{
4967 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
4968
4969 if (IsEqualGUID(iid, &IID_ID2D1TransformedGeometry)
4970 || IsEqualGUID(iid, &IID_ID2D1Geometry)
4971 || IsEqualGUID(iid, &IID_ID2D1Resource)
4972 || IsEqualGUID(iid, &IID_IUnknown))
4973 {
4974 ID2D1TransformedGeometry_AddRef(iface);
4975 *out = iface;
4976 return S_OK;
4977 }
4978
4979 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
4980
4981 *out = NULL;
4982 return E_NOINTERFACE;
4983}
4984
4986{
4987 struct d2d_geometry *geometry = impl_from_ID2D1TransformedGeometry(iface);
4989
4990 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
4991
4992 return refcount;
4993}
4994
4996{
4997 struct d2d_geometry *geometry = impl_from_ID2D1TransformedGeometry(iface);
4999
5000 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
5001
5002 if (!refcount)
5003 {
5004 geometry->outline.arc_faces = NULL;
5005 geometry->outline.arcs = NULL;
5006 geometry->outline.bezier_faces = NULL;
5007 geometry->outline.beziers = NULL;
5008 geometry->outline.faces = NULL;
5009 geometry->outline.vertices = NULL;
5010 geometry->fill.arc_vertices = NULL;
5011 geometry->fill.bezier_vertices = NULL;
5012 geometry->fill.faces = NULL;
5013 geometry->fill.vertices = NULL;
5014 ID2D1Geometry_Release(geometry->u.transformed.src_geometry);
5015 d2d_geometry_cleanup(geometry);
5016 free(geometry);
5017 }
5018
5019 return refcount;
5020}
5021
5024{
5025 struct d2d_geometry *geometry = impl_from_ID2D1TransformedGeometry(iface);
5026
5027 TRACE("iface %p, factory %p.\n", iface, factory);
5028
5029 ID2D1Factory_AddRef(*factory = geometry->factory);
5030}
5031
5034{
5035 struct d2d_geometry *geometry = impl_from_ID2D1TransformedGeometry(iface);
5037
5038 TRACE("iface %p, transform %p, bounds %p.\n", iface, transform, bounds);
5039
5040 g = geometry->transform;
5041 if (transform)
5043
5044 return ID2D1Geometry_GetBounds(geometry->u.transformed.src_geometry, &g, bounds);
5045}
5046
5048 float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform,
5049 float tolerance, D2D1_RECT_F *bounds)
5050{
5051 FIXME("iface %p, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, bounds %p stub!\n",
5052 iface, stroke_width, stroke_style, transform, tolerance, bounds);
5053
5054 return E_NOTIMPL;
5055}
5056
5058 D2D1_POINT_2F point, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform,
5059 float tolerance, BOOL *contains)
5060{
5061 struct d2d_geometry *geometry = impl_from_ID2D1TransformedGeometry(iface);
5063
5064 TRACE("iface %p, point %s, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, contains %p.\n",
5065 iface, debug_d2d_point_2f(&point), stroke_width, stroke_style, transform, tolerance, contains);
5066
5067 g = geometry->transform;
5068 stroke_width /= g.m11;
5069 if (transform)
5071
5072 if (tolerance <= 0.0f)
5073 tolerance = D2D1_DEFAULT_FLATTENING_TOLERANCE;
5074
5075 return ID2D1Geometry_StrokeContainsPoint(geometry->u.transformed.src_geometry, point, stroke_width, stroke_style,
5076 &g, tolerance, contains);
5077}
5078
5080 D2D1_POINT_2F point, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
5081{
5082 struct d2d_geometry *geometry = impl_from_ID2D1TransformedGeometry(iface);
5084
5085 TRACE("iface %p, point %s, transform %p, tolerance %.8e, contains %p.\n",
5086 iface, debug_d2d_point_2f(&point), transform, tolerance, contains);
5087
5088 g = geometry->transform;
5089 if (transform)
5091
5092 return ID2D1Geometry_FillContainsPoint(geometry->u.transformed.src_geometry, point, &g, tolerance, contains);
5093}
5094
5096 ID2D1Geometry *geometry, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_GEOMETRY_RELATION *relation)
5097{
5098 FIXME("iface %p, geometry %p, transform %p, tolerance %.8e, relation %p stub!\n",
5099 iface, geometry, transform, tolerance, relation);
5100
5101 return E_NOTIMPL;
5102}
5103
5107{
5108 struct d2d_geometry *geometry = impl_from_ID2D1TransformedGeometry(iface);
5110
5111 TRACE("iface %p, option %#x, transform %p, tolerance %.8e, sink %p.\n",
5112 iface, option, transform, tolerance, sink);
5113
5114 g = geometry->transform;
5115 if (transform)
5117
5118 return ID2D1Geometry_Simplify(geometry->u.transformed.src_geometry, option, &g, tolerance, sink);
5119}
5120
5122 const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1TessellationSink *sink)
5123{
5124 FIXME("iface %p, transform %p, tolerance %.8e, sink %p stub!\n", iface, transform, tolerance, sink);
5125
5126 return E_NOTIMPL;
5127}
5128
5130 ID2D1Geometry *geometry, D2D1_COMBINE_MODE combine_mode, const D2D1_MATRIX_3X2_F *transform,
5131 float tolerance, ID2D1SimplifiedGeometrySink *sink)
5132{
5133 FIXME("iface %p, geometry %p, combine_mode %#x, transform %p, tolerance %.8e, sink %p stub!\n",
5134 iface, geometry, combine_mode, transform, tolerance, sink);
5135
5136 return E_NOTIMPL;
5137}
5138
5141{
5142 FIXME("iface %p, transform %p, tolerance %.8e, sink %p stub!\n", iface, transform, tolerance, sink);
5143
5144 return E_NOTIMPL;
5145}
5146
5148 const D2D1_MATRIX_3X2_F *transform, float tolerance, float *area)
5149{
5150 FIXME("iface %p, transform %p, tolerance %.8e, area %p stub!\n", iface, transform, tolerance, area);
5151
5152 return E_NOTIMPL;
5153}
5154
5156 const D2D1_MATRIX_3X2_F *transform, float tolerance, float *length)
5157{
5158 FIXME("iface %p, transform %p, tolerance %.8e, length %p stub!\n", iface, transform, tolerance, length);
5159
5160 return E_NOTIMPL;
5161}
5162
5164 float length, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_POINT_2F *point,
5165 D2D1_POINT_2F *tangent)
5166{
5167 FIXME("iface %p, length %.8e, transform %p, tolerance %.8e, point %p, tangent %p stub!\n",
5168 iface, length, transform, tolerance, point, tangent);
5169
5170 return E_NOTIMPL;
5171}
5172
5174 ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance,
5176{
5177 FIXME("iface %p, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, sink %p stub!\n",
5178 iface, stroke_width, stroke_style, transform, tolerance, sink);
5179
5180 return E_NOTIMPL;
5181}
5182
5185{
5186 struct d2d_geometry *geometry = impl_from_ID2D1TransformedGeometry(iface);
5187
5188 TRACE("iface %p, src_geometry %p.\n", iface, src_geometry);
5189
5190 ID2D1Geometry_AddRef(*src_geometry = geometry->u.transformed.src_geometry);
5191}
5192
5195{
5196 struct d2d_geometry *geometry = impl_from_ID2D1TransformedGeometry(iface);
5197
5198 TRACE("iface %p, transform %p.\n", iface, transform);
5199
5200 *transform = geometry->u.transformed.transform;
5201}
5202
5203static const struct ID2D1TransformedGeometryVtbl d2d_transformed_geometry_vtbl =
5204{
5224};
5225
5227 ID2D1Geometry *src_geometry, const D2D_MATRIX_3X2_F *transform)
5228{
5229 struct d2d_geometry *src_impl;
5231
5233
5234 g = src_impl->transform;
5236 d2d_geometry_init(geometry, factory, &g, (ID2D1GeometryVtbl *)&d2d_transformed_geometry_vtbl);
5237 ID2D1Geometry_AddRef(geometry->u.transformed.src_geometry = src_geometry);
5238 geometry->u.transformed.transform = *transform;
5239 geometry->fill = src_impl->fill;
5240 geometry->outline = src_impl->outline;
5241}
5242
5244{
5245 return CONTAINING_RECORD(iface, struct d2d_geometry, ID2D1Geometry_iface);
5246}
5247
5249 REFIID iid, void **out)
5250{
5251 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
5252
5253 if (IsEqualGUID(iid, &IID_ID2D1GeometryGroup)
5254 || IsEqualGUID(iid, &IID_ID2D1Geometry)
5255 || IsEqualGUID(iid, &IID_ID2D1Resource)
5256 || IsEqualGUID(iid, &IID_IUnknown))
5257 {
5258 ID2D1GeometryGroup_AddRef(iface);
5259 *out = iface;
5260 return S_OK;
5261 }
5262
5263 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
5264
5265 *out = NULL;
5266 return E_NOINTERFACE;
5267}
5268
5270{
5271 struct d2d_geometry *geometry = impl_from_ID2D1GeometryGroup(iface);
5273
5274 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
5275
5276 return refcount;
5277}
5278
5280{
5281 struct d2d_geometry *geometry = impl_from_ID2D1GeometryGroup(iface);
5283 unsigned int i;
5284
5285 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
5286
5287 if (!refcount)
5288 {
5289 for (i = 0; i < geometry->u.group.geometry_count; ++i)
5290 ID2D1Geometry_Release(geometry->u.group.src_geometries[i]);
5291 free(geometry->u.group.src_geometries);
5292 d2d_geometry_cleanup(geometry);
5293 free(geometry);
5294 }
5295
5296 return refcount;
5297}
5298
5301{
5302 struct d2d_geometry *geometry = impl_from_ID2D1GeometryGroup(iface);
5303
5304 TRACE("iface %p, factory %p.\n", iface, factory);
5305
5306 ID2D1Factory_AddRef(*factory = geometry->factory);
5307}
5308
5311{
5312 struct d2d_geometry *geometry = impl_from_ID2D1GeometryGroup(iface);
5314 unsigned int i;
5315
5316 TRACE("iface %p, transform %p, bounds %p.\n", iface, transform, bounds);
5317
5318 bounds->left = FLT_MAX;
5319 bounds->top = FLT_MAX;
5320 bounds->right = -FLT_MAX;
5321 bounds->bottom = -FLT_MAX;
5322
5323 for (i = 0; i < geometry->u.group.geometry_count; ++i)
5324 {
5325 if (SUCCEEDED(ID2D1Geometry_GetBounds(geometry->u.group.src_geometries[i], transform, &rect)))
5327 }
5328
5329 return S_OK;
5330}
5331
5333 float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform,
5334 float tolerance, D2D1_RECT_F *bounds)
5335{
5336 FIXME("iface %p, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, bounds %p stub!\n",
5337 iface, stroke_width, stroke_style, transform, tolerance, bounds);
5338
5339 return E_NOTIMPL;
5340}
5341
5343 D2D1_POINT_2F point, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform,
5344 float tolerance, BOOL *contains)
5345{
5346 FIXME("iface %p, point %s, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, contains %p.\n",
5347 iface, debug_d2d_point_2f(&point), stroke_width, stroke_style, transform, tolerance, contains);
5348
5349 return E_NOTIMPL;
5350}
5351
5353 D2D1_POINT_2F point, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
5354{
5355 FIXME("iface %p, point %s, transform %p, tolerance %.8e, contains %p stub!.\n",
5356 iface, debug_d2d_point_2f(&point), transform, tolerance, contains);
5357
5358 return E_NOTIMPL;
5359}
5360
5362 ID2D1Geometry *geometry, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_GEOMETRY_RELATION *relation)
5363{
5364 FIXME("iface %p, geometry %p, transform %p, tolerance %.8e, relation %p stub!\n",
5365 iface, geometry, transform, tolerance, relation);
5366
5367 return E_NOTIMPL;
5368}
5369
5373{
5374 FIXME("iface %p, option %#x, transform %p, tolerance %.8e, sink %p stub!.\n",
5375 iface, option, transform, tolerance, sink);
5376
5377 return E_NOTIMPL;
5378}
5379
5381 const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1TessellationSink *sink)
5382{
5383 FIXME("iface %p, transform %p, tolerance %.8e, sink %p stub!\n", iface, transform, tolerance, sink);
5384
5385 return E_NOTIMPL;
5386}
5387
5389 ID2D1Geometry *geometry, D2D1_COMBINE_MODE combine_mode, const D2D1_MATRIX_3X2_F *transform,
5390 float tolerance, ID2D1SimplifiedGeometrySink *sink)
5391{
5392 FIXME("iface %p, geometry %p, combine_mode %#x, transform %p, tolerance %.8e, sink %p stub!\n",
5393 iface, geometry, combine_mode, transform, tolerance, sink);
5394
5395 return E_NOTIMPL;
5396}
5397
5400{
5401 FIXME("iface %p, transform %p, tolerance %.8e, sink %p stub!\n", iface, transform, tolerance, sink);
5402
5403 return E_NOTIMPL;
5404}
5405
5407 const D2D1_MATRIX_3X2_F *transform, float tolerance, float *area)
5408{
5409 FIXME("iface %p, transform %p, tolerance %.8e, area %p stub!\n", iface, transform, tolerance, area);
5410
5411 return E_NOTIMPL;
5412}
5413
5415 const D2D1_MATRIX_3X2_F *transform, float tolerance, float *length)
5416{
5417 FIXME("iface %p, transform %p, tolerance %.8e, length %p stub!\n", iface, transform, tolerance, length);
5418
5419 return E_NOTIMPL;
5420}
5421
5423 float length, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_POINT_2F *point,
5424 D2D1_POINT_2F *tangent)
5425{
5426 FIXME("iface %p, length %.8e, transform %p, tolerance %.8e, point %p, tangent %p stub!\n",
5427 iface, length, transform, tolerance, point, tangent);
5428
5429 return E_NOTIMPL;
5430}
5431
5433 ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance,
5435{
5436 FIXME("iface %p, stroke_width %.8e, stroke_style %p, transform %p, tolerance %.8e, sink %p stub!\n",
5437 iface, stroke_width, stroke_style, transform, tolerance, sink);
5438
5439 return E_NOTIMPL;
5440}
5441
5443{
5444 struct d2d_geometry *geometry = impl_from_ID2D1GeometryGroup(iface);
5445
5446 TRACE("iface %p.\n", iface);
5447
5448 return geometry->u.group.fill_mode;
5449}
5450
5452{
5453 struct d2d_geometry *geometry = impl_from_ID2D1GeometryGroup(iface);
5454
5455 TRACE("iface %p.\n", iface);
5456
5457 return geometry->u.group.geometry_count;
5458}
5459
5461 ID2D1Geometry **geometries, UINT32 geometry_count)
5462{
5463 struct d2d_geometry *geometry = impl_from_ID2D1GeometryGroup(iface);
5464 unsigned int i;
5465
5466 TRACE("iface %p, geometries %p, geometry_count %u.\n", iface, geometries, geometry_count);
5467
5468 geometry_count = min(geometry_count, geometry->u.group.geometry_count);
5469 for (i = 0; i < geometry_count; ++i)
5470 ID2D1Geometry_AddRef(geometries[i] = geometry->u.group.src_geometries[i]);
5471}
5472
5473static const struct ID2D1GeometryGroupVtbl d2d_geometry_group_vtbl =
5474{
5495};
5496
5498 D2D1_FILL_MODE fill_mode, ID2D1Geometry **geometries, unsigned int geometry_count)
5499{
5500 unsigned int i;
5501
5502 d2d_geometry_init(geometry, factory, &identity, (ID2D1GeometryVtbl *)&d2d_geometry_group_vtbl);
5503
5504 if (!(geometry->u.group.src_geometries = calloc(geometry_count, sizeof(*geometries))))
5505 {
5506 d2d_geometry_cleanup(geometry);
5507 return E_OUTOFMEMORY;
5508 }
5509
5510 for (i = 0; i < geometry_count; ++i)
5511 {
5512 ID2D1Geometry_AddRef(geometry->u.group.src_geometries[i] = geometries[i]);
5513 }
5514 geometry->u.group.geometry_count = geometry_count;
5515 geometry->u.group.fill_mode = fill_mode;
5516
5517 return S_OK;
5518}
5519
5521{
5522 if (!iface)
5523 return NULL;
5524 assert(iface->lpVtbl == (const ID2D1GeometryVtbl *)&d2d_ellipse_geometry_vtbl
5525 || iface->lpVtbl == (const ID2D1GeometryVtbl *)&d2d_path_geometry_vtbl
5526 || iface->lpVtbl == (const ID2D1GeometryVtbl *)&d2d_rectangle_geometry_vtbl
5527 || iface->lpVtbl == (const ID2D1GeometryVtbl *)&d2d_rounded_rectangle_geometry_vtbl
5528 || iface->lpVtbl == (const ID2D1GeometryVtbl *)&d2d_transformed_geometry_vtbl
5529 || iface->lpVtbl == (const ID2D1GeometryVtbl *)&d2d_geometry_group_vtbl);
5530 return CONTAINING_RECORD(iface, struct d2d_geometry, ID2D1Geometry_iface);
5531}
unsigned short UINT16
Definition: actypes.h:129
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ARRAY_SIZE(A)
Definition: main.h:20
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
const GUID IID_IUnknown
#define STDMETHODCALLTYPE
Definition: bdasup.h:9
struct _root root
r l[0]
Definition: byte_order.h:168
RECT rect
Definition: combotst.c:67
HDC dc
Definition: cylfrac.c:34
D2D1_FILL_MODE
Definition: d2d1.idl:84
@ D2D1_FILL_MODE_ALTERNATE
Definition: d2d1.idl:85
D2D1_FIGURE_BEGIN
Definition: d2d1.idl:99
@ D2D1_FIGURE_BEGIN_HOLLOW
Definition: d2d1.idl:101
@ D2D1_FIGURE_BEGIN_FILLED
Definition: d2d1.idl:100
D2D1_GEOMETRY_RELATION
Definition: d2d1.idl:142
D2D1_GEOMETRY_SIMPLIFICATION_OPTION
Definition: d2d1.idl:152
@ D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES
Definition: d2d1.idl:154
D2D1_PATH_SEGMENT
Definition: d2d1.idl:91
@ D2D1_PATH_SEGMENT_NONE
Definition: d2d1.idl:92
@ D2D1_PATH_SEGMENT_FORCE_ROUND_LINE_JOIN
Definition: d2d1.idl:94
D2D1_FIGURE_END
Definition: d2d1.idl:106
@ D2D1_FIGURE_END_CLOSED
Definition: d2d1.idl:108
@ D2D1_FIGURE_END_OPEN
Definition: d2d1.idl:107
D2D1_COMBINE_MODE
Definition: d2d1.idl:159
static BOOL d2d_matrix_invert(D2D_MATRIX_3X2_F *dst, const D2D_MATRIX_3X2_F *src)
Definition: d2d1_private.h:936
static const char * debug_d2d_point_2f(const D2D1_POINT_2F *point)
Definition: d2d1_private.h:993
static float d2d_point_dot(const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1)
Definition: d2d1_private.h:958
static void d2d_rect_expand(D2D1_RECT_F *dst, const D2D1_POINT_2F *point)
Definition: d2d1_private.h:969
static void d2d_matrix_multiply(D2D_MATRIX_3X2_F *a, const D2D_MATRIX_3X2_F *b)
Definition: d2d1_private.h:923
static BOOL d2d_array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
Definition: d2d1_private.h:897
static void d2d_point_set(D2D1_POINT_2F *dst, float x, float y)
Definition: d2d1_private.h:952
@ D2D_GEOMETRY_STATE_CLOSED
Definition: d2d1_private.h:469
@ D2D_GEOMETRY_STATE_ERROR
Definition: d2d1_private.h:467
@ D2D_GEOMETRY_STATE_FIGURE
Definition: d2d1_private.h:470
@ D2D_GEOMETRY_STATE_INITIAL
Definition: d2d1_private.h:466
@ D2D_GEOMETRY_STATE_OPEN
Definition: d2d1_private.h:468
static void d2d_point_transform(D2D1_POINT_2F *dst, const D2D1_MATRIX_3X2_F *matrix, float x, float y)
Definition: d2d1_private.h:963
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
HRESULT hr
Definition: delayimp.cpp:582
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static ULONG STDMETHODCALLTYPE d2d_rectangle_geometry_Release(ID2D1RectangleGeometry *iface)
Definition: geometry.c:4283
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Simplify(ID2D1PathGeometry1 *iface, D2D1_GEOMETRY_SIMPLIFICATION_OPTION option, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:3728
static BOOL d2d_path_geometry_add_fill_face(struct d2d_geometry *geometry, const struct d2d_cdt *cdt, const struct d2d_cdt_edge_ref *base_edge)
Definition: geometry.c:1614
static HRESULT STDMETHODCALLTYPE d2d_rectangle_geometry_QueryInterface(ID2D1RectangleGeometry *iface, REFIID iid, void **out)
Definition: geometry.c:4252
static const struct ID2D1PathGeometry1Vtbl d2d_path_geometry_vtbl
Definition: geometry.c:3939
static void d2d_fp_two_two_sum(float *out, const float *a, const float *b)
Definition: geometry.c:191
static HRESULT STDMETHODCALLTYPE d2d_geometry_group_GetBounds(ID2D1GeometryGroup *iface, const D2D1_MATRIX_3X2_F *transform, D2D1_RECT_F *bounds)
Definition: geometry.c:5309
static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_StrokeContainsPoint(ID2D1RoundedRectangleGeometry *iface, D2D1_POINT_2F point, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
Definition: geometry.c:4743
static HRESULT d2d_path_geometry_triangulate(struct d2d_geometry *geometry)
Definition: geometry.c:2282
static BOOL d2d_cdt_insert_segments(struct d2d_cdt *cdt, struct d2d_geometry *geometry)
Definition: geometry.c:1817
static HRESULT STDMETHODCALLTYPE d2d_rectangle_geometry_Simplify(ID2D1RectangleGeometry *iface, D2D1_GEOMETRY_SIMPLIFICATION_OPTION option, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:4465
static BOOL d2d_geometry_outline_add_bezier_segment(struct d2d_geometry *geometry, const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2)
Definition: geometry.c:2494
static void d2d_geometry_cleanup(struct d2d_geometry *geometry)
Definition: geometry.c:2719
#define D2D_FIGURE_FLAG_CLOSED
Definition: geometry.c:24
#define D2D_FP_EPS
Definition: geometry.c:30
static void d2d_cdt_destroy_edge(struct d2d_cdt *cdt, const struct d2d_cdt_edge_ref *e)
Definition: geometry.c:1343
static void d2d_cdt_edge_rot(struct d2d_cdt_edge_ref *dst, const struct d2d_cdt_edge_ref *src)
Definition: geometry.c:925
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_CompareWithGeometry(ID2D1PathGeometry1 *iface, ID2D1Geometry *geometry, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_GEOMETRY_RELATION *relation)
Definition: geometry.c:3674
static void d2d_cdt_edge_set_origin(const struct d2d_cdt *cdt, const struct d2d_cdt_edge_ref *e, size_t vertex)
Definition: geometry.c:971
static void STDMETHODCALLTYPE d2d_ellipse_geometry_GetEllipse(ID2D1EllipseGeometry *iface, D2D1_ELLIPSE *ellipse)
Definition: geometry.c:4154
static HRESULT STDMETHODCALLTYPE d2d_rectangle_geometry_ComputePointAtLength(ID2D1RectangleGeometry *iface, float length, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_POINT_2F *point, D2D1_POINT_2F *tangent)
Definition: geometry.c:4540
static void d2d_cdt_edge_set_destination(const struct d2d_cdt *cdt, const struct d2d_cdt_edge_ref *e, size_t vertex)
Definition: geometry.c:977
static BOOL d2d_figure_insert_vertex(struct d2d_figure *figure, size_t idx, D2D1_POINT_2F vertex)
Definition: geometry.c:820
static HRESULT STDMETHODCALLTYPE d2d_rectangle_geometry_Outline(ID2D1RectangleGeometry *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:4516
static ULONG STDMETHODCALLTYPE d2d_geometry_group_Release(ID2D1GeometryGroup *iface)
Definition: geometry.c:5279
static HRESULT STDMETHODCALLTYPE d2d_rectangle_geometry_StrokeContainsPoint(ID2D1RectangleGeometry *iface, D2D1_POINT_2F point, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
Definition: geometry.c:4351
static BOOL d2d_vertex_type_is_split_bezier(enum d2d_vertex_type t)
Definition: geometry.c:424
static BOOL d2d_geometry_intersect_line_line(struct d2d_geometry *geometry, struct d2d_geometry_intersections *intersections, const struct d2d_segment_idx *idx_p, const struct d2d_segment_idx *idx_q)
Definition: geometry.c:1921
static ULONG STDMETHODCALLTYPE d2d_ellipse_geometry_Release(ID2D1EllipseGeometry *iface)
Definition: geometry.c:4011
static BOOL d2d_point_on_bezier_segment(const D2D1_POINT_2F *q, const D2D1_POINT_2F *p0, const D2D1_BEZIER_SEGMENT *b, const D2D1_MATRIX_3X2_F *transform, float stroke_width, float tolerance)
Definition: geometry.c:595
static HRESULT STDMETHODCALLTYPE d2d_transformed_geometry_CompareWithGeometry(ID2D1TransformedGeometry *iface, ID2D1Geometry *geometry, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_GEOMETRY_RELATION *relation)
Definition: geometry.c:5095
static HRESULT STDMETHODCALLTYPE d2d_geometry_sink_Close(ID2D1GeometrySink *iface)
Definition: geometry.c:3224
static void STDMETHODCALLTYPE d2d_transformed_geometry_GetFactory(ID2D1TransformedGeometry *iface, ID2D1Factory **factory)
Definition: geometry.c:5022
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Tessellate(ID2D1PathGeometry1 *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1TessellationSink *sink)
Definition: geometry.c:3816
static const D2D1_MATRIX_3X2_F identity
Definition: geometry.c:32
void d2d_transformed_geometry_init(struct d2d_geometry *geometry, ID2D1Factory *factory, ID2D1Geometry *src_geometry, const D2D_MATRIX_3X2_F *transform)
Definition: geometry.c:5226
static HRESULT STDMETHODCALLTYPE d2d_geometry_group_ComputeArea(ID2D1GeometryGroup *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, float *area)
Definition: geometry.c:5406
static HRESULT STDMETHODCALLTYPE d2d_transformed_geometry_ComputeLength(ID2D1TransformedGeometry *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, float *length)
Definition: geometry.c:5155
static BOOL d2d_rect_check_overlap(const D2D_RECT_F *p, const D2D_RECT_F *q)
Definition: geometry.c:764
static BOOL d2d_geometry_get_first_bezier_segment_idx(struct d2d_geometry *geometry, struct d2d_segment_idx *idx)
Definition: geometry.c:3003
static BOOL d2d_figure_insert_bezier_controls(struct d2d_figure *figure, size_t idx, size_t count, const D2D1_POINT_2F *p)
Definition: geometry.c:876
static void d2d_curve_outline_vertex_set(struct d2d_curve_outline_vertex *a, const D2D1_POINT_2F *position, const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2, float prev_x, float prev_y, float next_x, float next_y)
Definition: geometry.c:158
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_ComputePointAtLength(ID2D1PathGeometry1 *iface, float length, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_POINT_2F *point, D2D1_POINT_2F *tangent)
Definition: geometry.c:3858
#define D2D_CDT_EDGE_FLAG_VISITED(r)
Definition: geometry.c:28
static BOOL d2d_geometry_intersect_bezier_bezier(struct d2d_geometry *geometry, struct d2d_geometry_intersections *intersections, const struct d2d_segment_idx *idx_p, float start_p, float end_p, const struct d2d_segment_idx *idx_q, float start_q, float end_q)
Definition: geometry.c:2070
static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_FillContainsPoint(ID2D1RoundedRectangleGeometry *iface, D2D1_POINT_2F point, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
Definition: geometry.c:4753
static HRESULT STDMETHODCALLTYPE d2d_geometry_group_GetWidenedBounds(ID2D1GeometryGroup *iface, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_RECT_F *bounds)
Definition: geometry.c:5332
static HRESULT STDMETHODCALLTYPE d2d_rectangle_geometry_ComputeArea(ID2D1RectangleGeometry *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, float *area)
Definition: geometry.c:4524
static HRESULT STDMETHODCALLTYPE d2d_geometry_sink_QueryInterface(ID2D1GeometrySink *iface, REFIID iid, void **out)
Definition: geometry.c:2748
static void STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_GetFactory(ID2D1RoundedRectangleGeometry *iface, ID2D1Factory **factory)
Definition: geometry.c:4715
static HRESULT STDMETHODCALLTYPE d2d_ellipse_geometry_ComputeLength(ID2D1EllipseGeometry *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, float *length)
Definition: geometry.c:4126
static BOOL d2d_cdt_connect(struct d2d_cdt *cdt, struct d2d_cdt_edge_ref *e, const struct d2d_cdt_edge_ref *a, const struct d2d_cdt_edge_ref *b)
Definition: geometry.c:1368
static BOOL d2d_geometry_add_bezier_line_intersections(struct d2d_geometry *geometry, struct d2d_geometry_intersections *intersections, const struct d2d_segment_idx *idx_p, const D2D1_POINT_2F **p, const struct d2d_segment_idx *idx_q, const D2D1_POINT_2F **q, float s)
Definition: geometry.c:1971
static void d2d_point_normalise(D2D1_POINT_2F *p)
Definition: geometry.c:411
static HRESULT STDMETHODCALLTYPE d2d_rectangle_geometry_ComputeLength(ID2D1RectangleGeometry *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, float *length)
Definition: geometry.c:4532
static HRESULT STDMETHODCALLTYPE d2d_ellipse_geometry_FillContainsPoint(ID2D1EllipseGeometry *iface, D2D1_POINT_2F point, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
Definition: geometry.c:4064
static void d2d_rect_union(D2D1_RECT_F *l, const D2D1_RECT_F *r)
Definition: geometry.c:756
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_QueryInterface(ID2D1PathGeometry1 *iface, REFIID iid, void **out)
Definition: geometry.c:3379
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_StrokeContainsPoint(ID2D1PathGeometry1 *iface, D2D1_POINT_2F point, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
Definition: geometry.c:3566
static size_t d2d_cdt_edge_origin(const struct d2d_cdt *cdt, const struct d2d_cdt_edge_ref *e)
Definition: geometry.c:961
static void d2d_cdt_edge_prev_origin(const struct d2d_cdt *cdt, struct d2d_cdt_edge_ref *dst, const struct d2d_cdt_edge_ref *src)
Definition: geometry.c:955
static HRESULT STDMETHODCALLTYPE d2d_ellipse_geometry_Tessellate(ID2D1EllipseGeometry *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1TessellationSink *sink)
Definition: geometry.c:4092
static HRESULT STDMETHODCALLTYPE d2d_transformed_geometry_Tessellate(ID2D1TransformedGeometry *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1TessellationSink *sink)
Definition: geometry.c:5121
static HRESULT STDMETHODCALLTYPE d2d_transformed_geometry_FillContainsPoint(ID2D1TransformedGeometry *iface, D2D1_POINT_2F point, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
Definition: geometry.c:5079
static ULONG STDMETHODCALLTYPE d2d_path_geometry_Release(ID2D1PathGeometry1 *iface)
Definition: geometry.c:3410
static ULONG STDMETHODCALLTYPE d2d_ellipse_geometry_AddRef(ID2D1EllipseGeometry *iface)
Definition: geometry.c:4001
static HRESULT STDMETHODCALLTYPE d2d_ellipse_geometry_ComputePointAtLength(ID2D1EllipseGeometry *iface, float length, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_POINT_2F *point, D2D1_POINT_2F *tangent)
Definition: geometry.c:4134
static void STDMETHODCALLTYPE d2d_geometry_sink_AddQuadraticBeziers(ID2D1GeometrySink *iface, const D2D1_QUADRATIC_BEZIER_SEGMENT *beziers, UINT32 bezier_count)
Definition: geometry.c:3280
HRESULT d2d_rounded_rectangle_geometry_init(struct d2d_geometry *geometry, ID2D1Factory *factory, const D2D1_ROUNDED_RECT *rounded_rect)
Definition: geometry.c:4876
static BOOL d2d_cdt_leftof(const struct d2d_cdt *cdt, size_t p, const struct d2d_cdt_edge_ref *e)
Definition: geometry.c:993
static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_CompareWithGeometry(ID2D1RoundedRectangleGeometry *iface, ID2D1Geometry *geometry, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_GEOMETRY_RELATION *relation)
Definition: geometry.c:4762
static HRESULT STDMETHODCALLTYPE d2d_rectangle_geometry_GetWidenedBounds(ID2D1RectangleGeometry *iface, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_RECT_F *bounds)
Definition: geometry.c:4341
static BOOL d2d_vertex_type_is_bezier(enum d2d_vertex_type t)
Definition: geometry.c:419
static const struct ID2D1EllipseGeometryVtbl d2d_ellipse_geometry_vtbl
Definition: geometry.c:4163
static HRESULT d2d_geometry_resolve_beziers(struct d2d_geometry *geometry)
Definition: geometry.c:3133
#define D2D_FIGURE_FLAG_HOLLOW
Definition: geometry.c:25
static void d2d_cdt_edge_tor(struct d2d_cdt_edge_ref *dst, const struct d2d_cdt_edge_ref *src)
Definition: geometry.c:937
static void d2d_point_lerp(D2D1_POINT_2F *out, const D2D1_POINT_2F *a, const D2D1_POINT_2F *b, float t)
Definition: geometry.c:390
static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_GetWidenedBounds(ID2D1RoundedRectangleGeometry *iface, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_RECT_F *bounds)
Definition: geometry.c:4733
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_ComputeLength(ID2D1PathGeometry1 *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, float *length)
Definition: geometry.c:3850
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Stream(ID2D1PathGeometry1 *iface, ID2D1GeometrySink *sink)
Definition: geometry.c:3894
static void STDMETHODCALLTYPE d2d_geometry_sink_AddLines(ID2D1GeometrySink *iface, const D2D1_POINT_2F *points, UINT32 count)
Definition: geometry.c:2840
static const struct ID2D1RectangleGeometryVtbl d2d_rectangle_geometry_vtbl
Definition: geometry.c:4569
static float d2d_cdt_ccw(const struct d2d_cdt *cdt, size_t a, size_t b, size_t c)
Definition: geometry.c:983
static void STDMETHODCALLTYPE d2d_rectangle_geometry_GetFactory(ID2D1RectangleGeometry *iface, ID2D1Factory **factory)
Definition: geometry.c:4299
static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_GetBounds(ID2D1RoundedRectangleGeometry *iface, const D2D1_MATRIX_3X2_F *transform, D2D1_RECT_F *bounds)
Definition: geometry.c:4725
static void d2d_fp_two_sum(float *out, float a, float b)
Definition: geometry.c:170
static HRESULT STDMETHODCALLTYPE d2d_geometry_group_FillContainsPoint(ID2D1GeometryGroup *iface, D2D1_POINT_2F point, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
Definition: geometry.c:5352
static BOOL d2d_geometry_intersect_self(struct d2d_geometry *geometry)
Definition: geometry.c:2197
static ULONG STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_Release(ID2D1RoundedRectangleGeometry *iface)
Definition: geometry.c:4699
static HRESULT STDMETHODCALLTYPE d2d_rectangle_geometry_Tessellate(ID2D1RectangleGeometry *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1TessellationSink *sink)
Definition: geometry.c:4498
static const struct ID2D1GeometrySinkVtbl d2d_geometry_sink_vtbl
Definition: geometry.c:3355
static HRESULT STDMETHODCALLTYPE d2d_transformed_geometry_Simplify(ID2D1TransformedGeometry *iface, D2D1_GEOMETRY_SIMPLIFICATION_OPTION option, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:5104
static HRESULT STDMETHODCALLTYPE d2d_rectangle_geometry_CombineWithGeometry(ID2D1RectangleGeometry *iface, ID2D1Geometry *geometry, D2D1_COMBINE_MODE combine_mode, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:4506
static HRESULT STDMETHODCALLTYPE d2d_geometry_group_ComputeLength(ID2D1GeometryGroup *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, float *length)
Definition: geometry.c:5414
static void STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_GetRoundedRect(ID2D1RoundedRectangleGeometry *iface, D2D1_ROUNDED_RECT *rounded_rect)
Definition: geometry.c:4844
static void d2d_outline_vertex_set(struct d2d_outline_vertex *v, float x, float y, float prev_x, float prev_y, float next_x, float next_y)
Definition: geometry.c:150
static struct d2d_geometry * impl_from_ID2D1PathGeometry1(ID2D1PathGeometry1 *iface)
Definition: geometry.c:3374
static BOOL d2d_cdt_incircle(const struct d2d_cdt *cdt, size_t a, size_t b, size_t c, size_t d)
Definition: geometry.c:1165
static ULONG STDMETHODCALLTYPE d2d_geometry_sink_AddRef(ID2D1GeometrySink *iface)
Definition: geometry.c:2767
static BOOL d2d_cdt_fixup(struct d2d_cdt *cdt, const struct d2d_cdt_edge_ref *base_edge)
Definition: geometry.c:1689
static void d2d_point_calculate_bezier(D2D1_POINT_2F *out, const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2, float t)
Definition: geometry.c:397
static void STDMETHODCALLTYPE d2d_transformed_geometry_GetSourceGeometry(ID2D1TransformedGeometry *iface, ID2D1Geometry **src_geometry)
Definition: geometry.c:5183
static HRESULT STDMETHODCALLTYPE d2d_geometry_group_CompareWithGeometry(ID2D1GeometryGroup *iface, ID2D1Geometry *geometry, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_GEOMETRY_RELATION *relation)
Definition: geometry.c:5361
static void d2d_cdt_incircle_refine1(struct d2d_fp_fin *fin, float *det_abt, size_t *det_abt_len, const float *det_ab, float a, const float *az, float b, const float *bz, const float *c)
Definition: geometry.c:1024
static void d2d_curve_vertex_set(struct d2d_curve_vertex *b, const D2D1_POINT_2F *p, float u, float v, float sign)
Definition: geometry.c:134
struct d2d_geometry * unsafe_impl_from_ID2D1Geometry(ID2D1Geometry *iface)
Definition: geometry.c:5520
static void STDMETHODCALLTYPE d2d_geometry_sink_SetSegmentFlags(ID2D1GeometrySink *iface, D2D1_PATH_SEGMENT flags)
Definition: geometry.c:2796
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_CombineWithGeometry(ID2D1PathGeometry1 *iface, ID2D1Geometry *geometry, D2D1_COMBINE_MODE combine_mode, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:3824
static BOOL d2d_figure_add_vertex(struct d2d_figure *figure, D2D1_POINT_2F vertex)
Definition: geometry.c:847
static void STDMETHODCALLTYPE d2d_geometry_sink_BeginFigure(ID2D1GeometrySink *iface, D2D1_POINT_2F start_point, D2D1_FIGURE_BEGIN figure_begin)
Definition: geometry.c:2804
static void d2d_cdt_splice(const struct d2d_cdt *cdt, const struct d2d_cdt_edge_ref *a, const struct d2d_cdt_edge_ref *b)
Definition: geometry.c:1294
static void d2d_point_subtract(D2D1_POINT_2F *out, const D2D1_POINT_2F *a, const D2D1_POINT_2F *b)
Definition: geometry.c:377
static BOOL d2d_cdt_insert_segment(struct d2d_cdt *cdt, struct d2d_geometry *geometry, const struct d2d_cdt_edge_ref *origin, struct d2d_cdt_edge_ref *edge, size_t end_vertex)
Definition: geometry.c:1758
static BOOL d2d_cdt_rightof(const struct d2d_cdt *cdt, size_t p, const struct d2d_cdt_edge_ref *e)
Definition: geometry.c:988
static HRESULT STDMETHODCALLTYPE d2d_ellipse_geometry_QueryInterface(ID2D1EllipseGeometry *iface, REFIID iid, void **out)
Definition: geometry.c:3980
static void d2d_cdt_incircle_refine2(struct d2d_fp_fin *fin, const struct d2d_fp_two_vec2 *a, const struct d2d_fp_two_vec2 *b, const float *bz, const struct d2d_fp_two_vec2 *c, const float *cz, const float *axt_det_bc, size_t axt_det_bc_len, const float *ayt_det_bc, size_t ayt_det_bc_len)
Definition: geometry.c:1043
static BOOL d2d_cdt_merge(struct d2d_cdt *cdt, struct d2d_cdt_edge_ref *left_outer, struct d2d_cdt_edge_ref *left_inner, struct d2d_cdt_edge_ref *right_inner, struct d2d_cdt_edge_ref *right_outer)
Definition: geometry.c:1385
static HRESULT STDMETHODCALLTYPE d2d_transformed_geometry_Widen(ID2D1TransformedGeometry *iface, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:5173
static HRESULT STDMETHODCALLTYPE d2d_ellipse_geometry_CompareWithGeometry(ID2D1EllipseGeometry *iface, ID2D1Geometry *geometry, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_GEOMETRY_RELATION *relation)
Definition: geometry.c:4073
static HRESULT STDMETHODCALLTYPE d2d_rectangle_geometry_GetBounds(ID2D1RectangleGeometry *iface, const D2D1_MATRIX_3X2_F *transform, D2D1_RECT_F *bounds)
Definition: geometry.c:4308
static HRESULT STDMETHODCALLTYPE d2d_geometry_group_Tessellate(ID2D1GeometryGroup *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1TessellationSink *sink)
Definition: geometry.c:5380
static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_Simplify(ID2D1RoundedRectangleGeometry *iface, D2D1_GEOMETRY_SIMPLIFICATION_OPTION option, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:4772
static void STDMETHODCALLTYPE d2d_rectangle_geometry_GetRect(ID2D1RectangleGeometry *iface, D2D1_RECT_F *rect)
Definition: geometry.c:4560
static HRESULT STDMETHODCALLTYPE d2d_transformed_geometry_ComputeArea(ID2D1TransformedGeometry *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, float *area)
Definition: geometry.c:5147
static HRESULT STDMETHODCALLTYPE d2d_geometry_group_QueryInterface(ID2D1GeometryGroup *iface, REFIID iid, void **out)
Definition: geometry.c:5248
static float d2d_point_length(const D2D1_POINT_2F *p)
Definition: geometry.c:406
static BOOL d2d_point_on_line_segment(const D2D1_POINT_2F *q, const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_MATRIX_3X2_F *transform, float stroke_width, float tolerance)
Definition: geometry.c:517
static BOOL d2d_cdt_create_edge(struct d2d_cdt *cdt, struct d2d_cdt_edge_ref *e)
Definition: geometry.c:1313
static void STDMETHODCALLTYPE d2d_geometry_sink_EndFigure(ID2D1GeometrySink *iface, D2D1_FIGURE_END figure_end)
Definition: geometry.c:2926
static void STDMETHODCALLTYPE d2d_geometry_group_GetFactory(ID2D1GeometryGroup *iface, ID2D1Factory **factory)
Definition: geometry.c:5299
static HRESULT STDMETHODCALLTYPE d2d_geometry_group_CombineWithGeometry(ID2D1GeometryGroup *iface, ID2D1Geometry *geometry, D2D1_COMBINE_MODE combine_mode, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:5388
static BOOL d2d_geometry_outline_add_join(struct d2d_geometry *geometry, const D2D1_POINT_2F *prev, const D2D1_POINT_2F *p0, const D2D1_POINT_2F *next)
Definition: geometry.c:2394
d2d_cdt_edge_next
Definition: geometry.c:40
@ D2D_EDGE_NEXT_ROT
Definition: geometry.c:42
@ D2D_EDGE_NEXT_ORIGIN
Definition: geometry.c:41
@ D2D_EDGE_NEXT_TOR
Definition: geometry.c:44
@ D2D_EDGE_NEXT_SYM
Definition: geometry.c:43
static void d2d_fp_fast_expansion_sum_zeroelim(float *out, size_t *out_len, const float *a, size_t a_len, const float *b, size_t b_len)
Definition: geometry.c:276
static ULONG STDMETHODCALLTYPE d2d_path_geometry_AddRef(ID2D1PathGeometry1 *iface)
Definition: geometry.c:3400
static void d2d_fp_two_product(float *out, float a, float b)
Definition: geometry.c:246
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_GetWidenedBounds(ID2D1PathGeometry1 *iface, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_RECT_F *bounds)
Definition: geometry.c:3557
#define D2D_CDT_EDGE_FLAG_FREED
Definition: geometry.c:27
static ULONG STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_AddRef(ID2D1RoundedRectangleGeometry *iface)
Definition: geometry.c:4689
static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_Tessellate(ID2D1RoundedRectangleGeometry *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1TessellationSink *sink)
Definition: geometry.c:4782
static BOOL d2d_cdt_generate_faces(const struct d2d_cdt *cdt, struct d2d_geometry *geometry)
Definition: geometry.c:1660
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_GetFigureCount(ID2D1PathGeometry1 *iface, UINT32 *count)
Definition: geometry.c:3915
static BOOL d2d_geometry_add_figure_outline(struct d2d_geometry *geometry, struct d2d_figure *figure, D2D1_FIGURE_END figure_end)
Definition: geometry.c:2610
static HRESULT STDMETHODCALLTYPE d2d_geometry_group_Widen(ID2D1GeometryGroup *iface, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:5432
static void d2d_fp_fast_two_sum(float *out, float a, float b)
Definition: geometry.c:182
void d2d_path_geometry_init(struct d2d_geometry *geometry, ID2D1Factory *factory)
Definition: geometry.c:3965
HRESULT d2d_geometry_group_init(struct d2d_geometry *geometry, ID2D1Factory *factory, D2D1_FILL_MODE fill_mode, ID2D1Geometry **geometries, unsigned int geometry_count)
Definition: geometry.c:5497
static ULONG STDMETHODCALLTYPE d2d_geometry_sink_Release(ID2D1GeometrySink *iface)
Definition: geometry.c:2776
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_GetSegmentCount(ID2D1PathGeometry1 *iface, UINT32 *count)
Definition: geometry.c:3901
static void STDMETHODCALLTYPE d2d_ellipse_geometry_GetFactory(ID2D1EllipseGeometry *iface, ID2D1Factory **factory)
Definition: geometry.c:4027
static void d2d_fp_four_det2x2(float *out, float ax, float ay, float bx, float by)
Definition: geometry.c:1000
static void d2d_path_geometry_free_figures(struct d2d_geometry *geometry)
Definition: geometry.c:2960
static HRESULT STDMETHODCALLTYPE d2d_ellipse_geometry_Widen(ID2D1EllipseGeometry *iface, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:4144
static void d2d_geometry_init(struct d2d_geometry *geometry, ID2D1Factory *factory, const D2D1_MATRIX_3X2_F *transform, const struct ID2D1GeometryVtbl *vtbl)
Definition: geometry.c:2734
static HRESULT STDMETHODCALLTYPE d2d_transformed_geometry_QueryInterface(ID2D1TransformedGeometry *iface, REFIID iid, void **out)
Definition: geometry.c:4964
static float d2d_point_ccw(const D2D1_POINT_2F *a, const D2D1_POINT_2F *b, const D2D1_POINT_2F *c)
Definition: geometry.c:432
static int __cdecl d2d_geometry_intersections_compare(const void *a, const void *b)
Definition: geometry.c:1907
static BOOL d2d_geometry_split_bezier(struct d2d_geometry *geometry, const struct d2d_segment_idx *idx)
Definition: geometry.c:3106
static const struct ID2D1RoundedRectangleGeometryVtbl d2d_rounded_rectangle_geometry_vtbl
Definition: geometry.c:4854
static struct d2d_geometry * impl_from_ID2D1EllipseGeometry(ID2D1EllipseGeometry *iface)
Definition: geometry.c:3975
static HRESULT STDMETHODCALLTYPE d2d_rectangle_geometry_FillContainsPoint(ID2D1RectangleGeometry *iface, D2D1_POINT_2F point, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
Definition: geometry.c:4427
static void d2d_cdt_cut_edges(struct d2d_cdt *cdt, struct d2d_cdt_edge_ref *end_edge, const struct d2d_cdt_edge_ref *base_edge, size_t start_vertex, size_t end_vertex)
Definition: geometry.c:1730
static void d2d_fp_two_product_presplit(float *out, float a, float b, const float *b_split)
Definition: geometry.c:234
static struct d2d_geometry * impl_from_ID2D1RectangleGeometry(ID2D1RectangleGeometry *iface)
Definition: geometry.c:4247
static void d2d_face_set(struct d2d_face *f, UINT16 v0, UINT16 v1, UINT16 v2)
Definition: geometry.c:143
static HRESULT STDMETHODCALLTYPE d2d_ellipse_geometry_Simplify(ID2D1EllipseGeometry *iface, D2D1_GEOMETRY_SIMPLIFICATION_OPTION option, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:4082
static BOOL d2d_geometry_intersect_bezier_line(struct d2d_geometry *geometry, struct d2d_geometry_intersections *intersections, const struct d2d_segment_idx *idx_p, const struct d2d_segment_idx *idx_q)
Definition: geometry.c:1997
static HRESULT STDMETHODCALLTYPE d2d_ellipse_geometry_ComputeArea(ID2D1EllipseGeometry *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, float *area)
Definition: geometry.c:4118
static HRESULT STDMETHODCALLTYPE d2d_ellipse_geometry_GetWidenedBounds(ID2D1EllipseGeometry *iface, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_RECT_F *bounds)
Definition: geometry.c:4044
static HRESULT STDMETHODCALLTYPE d2d_ellipse_geometry_GetBounds(ID2D1EllipseGeometry *iface, const D2D1_MATRIX_3X2_F *transform, D2D1_RECT_F *bounds)
Definition: geometry.c:4036
static BOOL d2d_path_geometry_point_inside(const struct d2d_geometry *geometry, const D2D1_POINT_2F *probe, BOOL triangles_only)
Definition: geometry.c:1567
static ULONG STDMETHODCALLTYPE d2d_transformed_geometry_AddRef(ID2D1TransformedGeometry *iface)
Definition: geometry.c:4985
static float d2d_fp_estimate(float *a, size_t len)
Definition: geometry.c:265
static HRESULT STDMETHODCALLTYPE d2d_transformed_geometry_CombineWithGeometry(ID2D1TransformedGeometry *iface, ID2D1Geometry *geometry, D2D1_COMBINE_MODE combine_mode, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:5129
static void d2d_fp_square(float *out, float a)
Definition: geometry.c:254
static struct d2d_geometry * impl_from_ID2D1TransformedGeometry(ID2D1TransformedGeometry *iface)
Definition: geometry.c:4959
static void d2d_point_scale(D2D1_POINT_2F *p, float scale)
Definition: geometry.c:384
static HRESULT STDMETHODCALLTYPE d2d_ellipse_geometry_CombineWithGeometry(ID2D1EllipseGeometry *iface, ID2D1Geometry *geometry, D2D1_COMBINE_MODE combine_mode, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:4100
static const struct ID2D1TransformedGeometryVtbl d2d_transformed_geometry_vtbl
Definition: geometry.c:5203
static float d2d_geometry_bezier_ccw(struct d2d_geometry *geometry, const struct d2d_segment_idx *idx)
Definition: geometry.c:3097
static UINT32 STDMETHODCALLTYPE d2d_geometry_group_GetSourceGeometryCount(ID2D1GeometryGroup *iface)
Definition: geometry.c:5451
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_GetBounds(ID2D1PathGeometry1 *iface, const D2D1_MATRIX_3X2_F *transform, D2D1_RECT_F *bounds)
Definition: geometry.c:3436
static BOOL d2d_geometry_outline_add_arc_quadrant(struct d2d_geometry *geometry, const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2)
Definition: geometry.c:2558
static void d2d_cdt_edge_next_left(const struct d2d_cdt *cdt, struct d2d_cdt_edge_ref *dst, const struct d2d_cdt_edge_ref *src)
Definition: geometry.c:943
static void STDMETHODCALLTYPE d2d_geometry_group_GetSourceGeometries(ID2D1GeometryGroup *iface, ID2D1Geometry **geometries, UINT32 geometry_count)
Definition: geometry.c:5460
static D2D1_FILL_MODE STDMETHODCALLTYPE d2d_geometry_group_GetFillMode(ID2D1GeometryGroup *iface)
Definition: geometry.c:5442
static void STDMETHODCALLTYPE d2d_geometry_sink_AddBezier(ID2D1GeometrySink *iface, const D2D1_BEZIER_SEGMENT *bezier)
Definition: geometry.c:3265
d2d_vertex_type
Definition: geometry.c:48
@ D2D_VERTEX_TYPE_LINE
Definition: geometry.c:50
@ D2D_VERTEX_TYPE_END
Definition: geometry.c:53
@ D2D_VERTEX_TYPE_BEZIER
Definition: geometry.c:51
@ D2D_VERTEX_TYPE_SPLIT_BEZIER
Definition: geometry.c:52
@ D2D_VERTEX_TYPE_NONE
Definition: geometry.c:49
static BOOL d2d_geometry_check_bezier_overlap(struct d2d_geometry *geometry, const struct d2d_segment_idx *idx_p, const struct d2d_segment_idx *idx_q)
Definition: geometry.c:3015
static ULONG STDMETHODCALLTYPE d2d_rectangle_geometry_AddRef(ID2D1RectangleGeometry *iface)
Definition: geometry.c:4273
static void d2d_fp_two_two_diff(float *out, const float *a, const float *b)
Definition: geometry.c:212
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Widen(ID2D1PathGeometry1 *iface, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:3867
static HRESULT STDMETHODCALLTYPE d2d_geometry_group_Simplify(ID2D1GeometryGroup *iface, D2D1_GEOMETRY_SIMPLIFICATION_OPTION option, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:5370
static BOOL d2d_figure_add_bezier_controls(struct d2d_figure *figure, size_t count, const D2D1_POINT_2F *p)
Definition: geometry.c:894
static size_t d2d_cdt_edge_destination(const struct d2d_cdt *cdt, const struct d2d_cdt_edge_ref *e)
Definition: geometry.c:966
static void d2d_cdt_edge_next_origin(const struct d2d_cdt *cdt, struct d2d_cdt_edge_ref *dst, const struct d2d_cdt_edge_ref *src)
Definition: geometry.c:949
static void d2d_rect_get_bezier_bounds(D2D_RECT_F *bounds, const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2)
Definition: geometry.c:769
static HRESULT STDMETHODCALLTYPE d2d_ellipse_geometry_StrokeContainsPoint(ID2D1EllipseGeometry *iface, D2D1_POINT_2F point, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
Definition: geometry.c:4054
static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_ComputeArea(ID2D1RoundedRectangleGeometry *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, float *area)
Definition: geometry.c:4808
static HRESULT STDMETHODCALLTYPE d2d_rectangle_geometry_Widen(ID2D1RectangleGeometry *iface, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:4550
static void STDMETHODCALLTYPE d2d_path_geometry_GetFactory(ID2D1PathGeometry1 *iface, ID2D1Factory **factory)
Definition: geometry.c:3427
static void STDMETHODCALLTYPE d2d_geometry_sink_AddArc(ID2D1GeometrySink *iface, const D2D1_ARC_SEGMENT *arc)
Definition: geometry.c:3334
static struct d2d_geometry * impl_from_ID2D1RoundedRectangleGeometry(ID2D1RoundedRectangleGeometry *iface)
Definition: geometry.c:4663
static BOOL d2d_geometry_get_next_bezier_segment_idx(struct d2d_geometry *geometry, struct d2d_segment_idx *idx)
Definition: geometry.c:3010
static ULONG STDMETHODCALLTYPE d2d_transformed_geometry_Release(ID2D1TransformedGeometry *iface)
Definition: geometry.c:4995
static struct d2d_geometry * impl_from_ID2D1GeometryGroup(ID2D1GeometryGroup *iface)
Definition: geometry.c:5243
HRESULT d2d_rectangle_geometry_init(struct d2d_geometry *geometry, ID2D1Factory *factory, const D2D1_RECT_F *rect)
Definition: geometry.c:4591
static BOOL d2d_figure_add_original_bezier_controls(struct d2d_figure *figure, size_t count, const D2D1_POINT_2F *p)
Definition: geometry.c:909
static HRESULT STDMETHODCALLTYPE d2d_path_geometry1_ComputePointAndSegmentAtLength(ID2D1PathGeometry1 *iface, float length, UINT32 start_segment, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_POINT_DESCRIPTION *point_desc)
Definition: geometry.c:3929
static void d2d_fp_sub_det3x3(float *out, size_t *out_len, const struct d2d_fp_two_vec2 *a, const float *det2x2)
Definition: geometry.c:1010
static ULONG STDMETHODCALLTYPE d2d_geometry_group_AddRef(ID2D1GeometryGroup *iface)
Definition: geometry.c:5269
static HRESULT STDMETHODCALLTYPE d2d_geometry_group_StrokeContainsPoint(ID2D1GeometryGroup *iface, D2D1_POINT_2F point, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
Definition: geometry.c:5342
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Open(ID2D1PathGeometry1 *iface, ID2D1GeometrySink **sink)
Definition: geometry.c:3877
static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_QueryInterface(ID2D1RoundedRectangleGeometry *iface, REFIID iid, void **out)
Definition: geometry.c:4668
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_FillContainsPoint(ID2D1PathGeometry1 *iface, D2D1_POINT_2F point, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
Definition: geometry.c:3651
static struct d2d_geometry * impl_from_ID2D1GeometrySink(ID2D1GeometrySink *iface)
Definition: geometry.c:2743
static void STDMETHODCALLTYPE d2d_geometry_sink_AddBeziers(ID2D1GeometrySink *iface, const D2D1_BEZIER_SEGMENT *beziers, UINT32 count)
Definition: geometry.c:2868
static BOOL d2d_path_geometry_add_figure(struct d2d_geometry *geometry)
Definition: geometry.c:2372
static void d2d_fp_two_diff_tail(float *out, float a, float b, float x)
Definition: geometry.c:201
static BOOL d2d_geometry_intersections_add(struct d2d_geometry_intersections *i, const struct d2d_segment_idx *segment_idx, float t, D2D1_POINT_2F p)
Definition: geometry.c:1885
static const struct ID2D1GeometryGroupVtbl d2d_geometry_group_vtbl
Definition: geometry.c:5473
static HRESULT STDMETHODCALLTYPE d2d_transformed_geometry_ComputePointAtLength(ID2D1TransformedGeometry *iface, float length, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_POINT_2F *point, D2D1_POINT_2F *tangent)
Definition: geometry.c:5163
static BOOL d2d_cdt_triangulate(struct d2d_cdt *cdt, size_t start_vertex, size_t vertex_count, struct d2d_cdt_edge_ref *left_edge, struct d2d_cdt_edge_ref *right_edge)
Definition: geometry.c:1480
static HRESULT STDMETHODCALLTYPE d2d_ellipse_geometry_Outline(ID2D1EllipseGeometry *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:4110
static void STDMETHODCALLTYPE d2d_geometry_sink_AddLine(ID2D1GeometrySink *iface, D2D1_POINT_2F point)
Definition: geometry.c:3258
static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_ComputePointAtLength(ID2D1RoundedRectangleGeometry *iface, float length, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_POINT_2F *point, D2D1_POINT_2F *tangent)
Definition: geometry.c:4824
static HRESULT STDMETHODCALLTYPE d2d_transformed_geometry_Outline(ID2D1TransformedGeometry *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:5139
static void STDMETHODCALLTYPE d2d_geometry_sink_SetFillMode(ID2D1GeometrySink *iface, D2D1_FILL_MODE mode)
Definition: geometry.c:2785
static void STDMETHODCALLTYPE d2d_geometry_sink_AddQuadraticBezier(ID2D1GeometrySink *iface, const D2D1_QUADRATIC_BEZIER_SEGMENT *bezier)
Definition: geometry.c:3272
static void d2d_fp_scale_expansion_zeroelim(float *out, size_t *out_len, const float *a, size_t a_len, float b)
Definition: geometry.c:350
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_Outline(ID2D1PathGeometry1 *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:3834
static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_Outline(ID2D1RoundedRectangleGeometry *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:4800
static void STDMETHODCALLTYPE d2d_transformed_geometry_GetTransform(ID2D1TransformedGeometry *iface, D2D1_MATRIX_3X2_F *transform)
Definition: geometry.c:5193
static HRESULT STDMETHODCALLTYPE d2d_transformed_geometry_StrokeContainsPoint(ID2D1TransformedGeometry *iface, D2D1_POINT_2F point, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, BOOL *contains)
Definition: geometry.c:5057
static void d2d_fp_split(float *out, float a)
Definition: geometry.c:224
static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_Widen(ID2D1RoundedRectangleGeometry *iface, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:4834
static void d2d_geometry_flatten_cubic(ID2D1SimplifiedGeometrySink *sink, const D2D1_POINT_2F *p0, const D2D1_BEZIER_SEGMENT *b, float tolerance)
Definition: geometry.c:3683
static int __cdecl d2d_cdt_compare_vertices(const void *a, const void *b)
Definition: geometry.c:1553
static void d2d_cdt_edge_sym(struct d2d_cdt_edge_ref *dst, const struct d2d_cdt_edge_ref *src)
Definition: geometry.c:931
static BOOL d2d_geometry_apply_intersections(struct d2d_geometry *geometry, struct d2d_geometry_intersections *intersections)
Definition: geometry.c:2131
static HRESULT STDMETHODCALLTYPE d2d_geometry_group_ComputePointAtLength(ID2D1GeometryGroup *iface, float length, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_POINT_2F *point, D2D1_POINT_2F *tangent)
Definition: geometry.c:5422
static HRESULT STDMETHODCALLTYPE d2d_transformed_geometry_GetWidenedBounds(ID2D1TransformedGeometry *iface, float stroke_width, ID2D1StrokeStyle *stroke_style, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_RECT_F *bounds)
Definition: geometry.c:5047
static void d2d_rect_get_bezier_segment_bounds(D2D_RECT_F *bounds, const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2, float start, float end)
Definition: geometry.c:803
static BOOL d2d_geometry_get_bezier_segment_idx(struct d2d_geometry *geometry, struct d2d_segment_idx *idx, BOOL next)
Definition: geometry.c:2978
static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_ComputeLength(ID2D1RoundedRectangleGeometry *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, float *length)
Definition: geometry.c:4816
static BOOL d2d_geometry_fill_add_arc_triangle(struct d2d_geometry *geometry, const D2D1_POINT_2F *p0, const D2D1_POINT_2F *p1, const D2D1_POINT_2F *p2)
Definition: geometry.c:2701
static HRESULT STDMETHODCALLTYPE d2d_transformed_geometry_GetBounds(ID2D1TransformedGeometry *iface, const D2D1_MATRIX_3X2_F *transform, D2D1_RECT_F *bounds)
Definition: geometry.c:5032
static HRESULT STDMETHODCALLTYPE d2d_rounded_rectangle_geometry_CombineWithGeometry(ID2D1RoundedRectangleGeometry *iface, ID2D1Geometry *geometry, D2D1_COMBINE_MODE combine_mode, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:4790
static HRESULT STDMETHODCALLTYPE d2d_path_geometry_ComputeArea(ID2D1PathGeometry1 *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, float *area)
Definition: geometry.c:3842
static BOOL d2d_geometry_outline_add_line_segment(struct d2d_geometry *geometry, const D2D1_POINT_2F *p0, const D2D1_POINT_2F *next)
Definition: geometry.c:2453
static HRESULT STDMETHODCALLTYPE d2d_rectangle_geometry_CompareWithGeometry(ID2D1RectangleGeometry *iface, ID2D1Geometry *geometry, const D2D1_MATRIX_3X2_F *transform, float tolerance, D2D1_GEOMETRY_RELATION *relation)
Definition: geometry.c:4456
static HRESULT STDMETHODCALLTYPE d2d_geometry_group_Outline(ID2D1GeometryGroup *iface, const D2D1_MATRIX_3X2_F *transform, float tolerance, ID2D1SimplifiedGeometrySink *sink)
Definition: geometry.c:5398
HRESULT d2d_ellipse_geometry_init(struct d2d_geometry *geometry, ID2D1Factory *factory, const D2D1_ELLIPSE *ellipse)
Definition: geometry.c:4185
WORD face[3]
Definition: mesh.c:4854
unsigned int idx
Definition: utils.c:40
#define assert(_expr)
Definition: assert.h:32
#define __cdecl
Definition: corecrt.h:121
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
#define FLT_MANT_DIG
Definition: float.h:36
#define _MCW_PC
Definition: float.h:67
_ACRTIMP unsigned int __cdecl _controlfp(unsigned int, unsigned int)
Definition: math.c:1288
#define FLT_MAX
Definition: float.h:37
#define _PC_24
Definition: float.h:83
#define isinf(x)
Definition: math.h:359
_ACRTIMP double __cdecl fabs(double)
_ACRTIMP float __cdecl cosf(float)
Definition: cosf.c:13
_ACRTIMP float __cdecl sinf(float)
Definition: sinf.c:13
#define INFINITY
Definition: math.h:272
_ACRTIMP float __cdecl fabsf(float)
_ACRTIMP float __cdecl atan2f(float, float)
Definition: atan2f.c:51
_ACRTIMP void __cdecl qsort(void *, size_t, size_t, int(__cdecl *)(const void *, const void *))
return ret
Definition: mutex.c:147
POINTL point
Definition: edittest.c:50
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
const GLdouble * v
Definition: gl.h:2040
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLclampf GLclampf GLclampf alpha
Definition: gl.h:1740
GLdouble s
Definition: gl.h:2039
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble t
Definition: gl.h:2047
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLuint GLenum GLenum transform
Definition: glext.h:9407
GLbyte GLbyte bz
Definition: glext.h:8766
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble GLdouble w2
Definition: glext.h:8308
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:9032
GLenum src
Definition: glext.h:6340
const GLubyte * c
Definition: glext.h:8905
GLenum GLint GLuint mask
Definition: glext.h:6028
GLenum GLuint GLint GLenum face
Definition: glext.h:7025
GLfloat f
Definition: glext.h:7540
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum mode
Definition: glext.h:6217
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLsizei GLenum GLboolean sink
Definition: glext.h:5672
GLboolean GLboolean g
Definition: glext.h:6204
GLfloat v0
Definition: glext.h:6061
GLfloat GLfloat p
Definition: glext.h:8902
GLfloat GLfloat GLfloat GLfloat v3
Definition: glext.h:6064
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLfloat GLfloat v1
Definition: glext.h:6062
GLfloat GLfloat GLfloat v2
Definition: glext.h:6063
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLsizei const GLfloat * points
Definition: glext.h:8112
GLbyte by
Definition: glext.h:8766
const GLfloat * m
Definition: glext.h:10848
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
voidpf uLong int origin
Definition: ioapi.h:144
#define d
Definition: ke_i.h:81
#define e
Definition: ke_i.h:82
#define f
Definition: ke_i.h:83
#define a
Definition: ke_i.h:78
#define c
Definition: ke_i.h:80
#define b
Definition: ke_i.h:79
#define debugstr_guid
Definition: kernel32.h:35
GLint dy
Definition: linetemp.h:97
GLint dx
Definition: linetemp.h:97
#define sign(x)
Definition: mapdesc.cc:613
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
struct task_struct * current
Definition: linux.c:32
UCHAR ab[sizeof("Hello World!") -1]
Definition: fdi.c:106
static CRYPT_DATA_BLOB b1[]
Definition: msg.c:529
int vertex_count
Definition: d3drm.c:3528
static DNS_RECORDW r1
Definition: record.c:37
static DNS_RECORDW r2
Definition: record.c:38
static const LARGE_INTEGER *static const HANDLE const LARGE_INTEGER *static PSLIST_ENTRY PSLIST_ENTRY last
Definition: sync.c:64
static const WCHAR tb[]
Definition: suminfo.c:431
#define min(a, b)
Definition: monoChain.cc:55
int k
Definition: mpi.c:3369
#define sqrtf(x)
Definition: mymath.h:59
static Real area(Real A[2], Real B[2], Real C[2])
Definition: polyDBG.cc:50
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define REFIID
Definition: guiddef.h:118
static int sum(int x_, int y_)
Definition: ptr2_test.cpp:35
#define swap(a, b)
Definition: qsort.c:63
static unsigned __int64 next
Definition: rand_nt.c:6
#define calloc
Definition: rosglue.h:14
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
D2D1_POINT_2F point
Definition: d2d1.idl:338
D2D1_POINT_2F point1
Definition: d2d1.idl:299
D2D1_POINT_2F point3
Definition: d2d1.idl:301
D2D1_POINT_2F point2
Definition: d2d1.idl:300
float radiusY
Definition: d2d1.idl:327
D2D1_POINT_2F point
Definition: d2d1.idl:325
float radiusX
Definition: d2d1.idl:326
D2D1_RECT_F rect
Definition: d2d1.idl:318
float top
Definition: dcommon.idl:106
float bottom
Definition: dcommon.idl:108
float right
Definition: dcommon.idl:107
float left
Definition: dcommon.idl:105
long bottom
Definition: dcommon.idl:29
long right
Definition: dcommon.idl:29
long left
Definition: dcommon.idl:29
long top
Definition: dcommon.idl:29
LONG y
Definition: windef.h:130
LONG x
Definition: windef.h:129
enum d2d_cdt_edge_next r
Definition: geometry.c:86
struct d2d_cdt_edge_ref next[4]
Definition: geometry.c:91
unsigned int flags
Definition: geometry.c:93
size_t edges_size
Definition: geometry.c:99
size_t edge_count
Definition: geometry.c:100
const D2D1_POINT_2F * vertices
Definition: geometry.c:103
struct d2d_cdt_edge * edges
Definition: geometry.c:98
size_t free_edge
Definition: geometry.c:101
D2D1_POINT_2F * vertices
Definition: geometry.c:65
size_t original_bezier_control_count
Definition: geometry.c:77
D2D1_POINT_2F * bezier_controls
Definition: geometry.c:71
D2D1_RECT_F bounds
Definition: geometry.c:79
size_t bezier_control_count
Definition: geometry.c:73
size_t vertex_count
Definition: geometry.c:69
size_t vertex_types_size
Definition: geometry.c:68
size_t bezier_controls_size
Definition: geometry.c:72
enum d2d_vertex_type * vertex_types
Definition: geometry.c:67
D2D1_POINT_2F * original_bezier_controls
Definition: geometry.c:75
size_t vertices_size
Definition: geometry.c:66
unsigned int flags
Definition: geometry.c:80
size_t original_bezier_controls_size
Definition: geometry.c:76
float * now
Definition: geometry.c:130
float * other
Definition: geometry.c:130
size_t length
Definition: geometry.c:131
float y[2]
Definition: geometry.c:125
float x[2]
Definition: geometry.c:124
struct d2d_geometry_intersection * intersections
Definition: geometry.c:117
struct d2d_curve_outline_vertex * beziers
Definition: d2d1_private.h:538
struct d2d_geometry::@243::@248 transformed
struct d2d_geometry::@243::@245 path
union d2d_geometry::@243 u
ID2D1Geometry * src_geometry
Definition: d2d1_private.h:585
D2D1_ELLIPSE ellipse
Definition: d2d1_private.h:559
D2D_MATRIX_3X2_F transform
Definition: d2d1_private.h:508
ID2D1Geometry ID2D1Geometry_iface
Definition: d2d1_private.h:503
struct d2d_geometry::@243::@246 rectangle
D2D1_ROUNDED_RECT rounded_rect
Definition: d2d1_private.h:581
UINT32 geometry_count
Definition: d2d1_private.h:591
size_t bezier_count
Definition: d2d1_private.h:540
struct d2d_geometry::@243::@249 group
ID2D1Factory * factory
Definition: d2d1_private.h:506
struct d2d_geometry::@243::@247 rounded_rectangle
struct d2d_geometry::@241 fill
struct d2d_geometry::@242 outline
D2D1_RECT_F bounds
Definition: d2d1_private.h:573
size_t vertex_idx
Definition: geometry.c:59
size_t figure_idx
Definition: geometry.c:58
size_t control_idx
Definition: geometry.c:60
Definition: main.c:439
Definition: getopt.h:109
Definition: tools.h:99
Definition: mesh.c:4665
#define max(a, b)
Definition: svc.c:63
ecx edi movl ebx edx edi decl ecx esi eax jecxz decl eax andl eax esi movl edx movl TEMP incl eax andl eax ecx incl ebx testl eax jnz xchgl ecx incl TEMP esp ecx subl ebx pushl ecx ecx edx ecx shrl ecx mm0 mm4 mm0 mm4 mm1 mm5 mm1 mm5 mm2 mm6 mm2 mm6 mm3 mm7 mm3 mm7 paddd mm0 paddd mm4 paddd mm0 paddd mm4 paddd mm0 paddd mm4 movq mm1 movq mm5 psrlq mm1 psrlq mm5 paddd mm0 paddd mm4 psrad mm0 psrad mm4 packssdw mm0 packssdw mm4 mm1 punpckldq mm0 pand mm1 pand mm0 por mm1 movq edi esi edx edi decl ecx jnz popl ecx andl ecx jecxz mm0 mm0 mm1 mm1 mm2 mm2 mm3 mm3 paddd mm0 paddd mm0 paddd mm0 movq mm1 psrlq mm1 paddd mm0 psrad mm0 packssdw mm0 movd eax movw ax
Definition: synth_sse3d.h:180
#define bsearch
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t UINT32
Definition: typedefs.h:59
uint32_t ULONG
Definition: typedefs.h:59
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
#define D2DERR_WRONG_STATE
Definition: winerror.h:7352
#define E_NOINTERFACE
Definition: winerror.h:3479
#define D2DERR_UNSUPPORTED_OPERATION
Definition: winerror.h:7354