Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim: set ts=8 sts=4 et sw=4 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "DecomposeIntoNoRepeatTriangles.h"
8 : #include "gfxMatrix.h"
9 :
10 : namespace mozilla {
11 : namespace gl {
12 :
13 : void
14 0 : RectTriangles::AppendRectToCoordArray(InfallibleTArray<coord>& array,
15 : GLfloat x0, GLfloat y0,
16 : GLfloat x1, GLfloat y1)
17 : {
18 0 : coord* v = array.AppendElements(6);
19 :
20 0 : v[0].x = x0; v[0].y = y0;
21 0 : v[1].x = x1; v[1].y = y0;
22 0 : v[2].x = x0; v[2].y = y1;
23 0 : v[3].x = x0; v[3].y = y1;
24 0 : v[4].x = x1; v[4].y = y0;
25 0 : v[5].x = x1; v[5].y = y1;
26 0 : }
27 :
28 : void
29 0 : RectTriangles::addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
30 : GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1,
31 : bool flip_y /* = false */)
32 : {
33 0 : if (flip_y) {
34 0 : std::swap(ty0, ty1);
35 : }
36 0 : AppendRectToCoordArray(mVertexCoords, x0, y0, x1, y1);
37 0 : AppendRectToCoordArray(mTexCoords, tx0, ty0, tx1, ty1);
38 0 : }
39 :
40 : static GLfloat
41 0 : WrapTexCoord(GLfloat v)
42 : {
43 : // This should return values in range [0, 1.0)
44 0 : return v - floorf(v);
45 : }
46 :
47 : void
48 0 : DecomposeIntoNoRepeatTriangles(const gfx::IntRect& aTexCoordRect,
49 : const gfx::IntSize& aTexSize,
50 : RectTriangles& aRects,
51 : bool aFlipY /* = false */)
52 : {
53 : // normalize this
54 0 : gfx::IntRect tcr(aTexCoordRect);
55 0 : while (tcr.x >= aTexSize.width)
56 0 : tcr.x -= aTexSize.width;
57 0 : while (tcr.y >= aTexSize.height)
58 0 : tcr.y -= aTexSize.height;
59 :
60 : // Compute top left and bottom right tex coordinates
61 : GLfloat tl[2] =
62 0 : { GLfloat(tcr.x) / GLfloat(aTexSize.width),
63 0 : GLfloat(tcr.y) / GLfloat(aTexSize.height) };
64 : GLfloat br[2] =
65 0 : { GLfloat(tcr.XMost()) / GLfloat(aTexSize.width),
66 0 : GLfloat(tcr.YMost()) / GLfloat(aTexSize.height) };
67 :
68 : // then check if we wrap in either the x or y axis; if we do,
69 : // then also use fmod to figure out the "true" non-wrapping
70 : // texture coordinates.
71 :
72 0 : bool xwrap = false, ywrap = false;
73 0 : if (tcr.x < 0 || tcr.x > aTexSize.width ||
74 0 : tcr.XMost() < 0 || tcr.XMost() > aTexSize.width)
75 : {
76 0 : xwrap = true;
77 0 : tl[0] = WrapTexCoord(tl[0]);
78 0 : br[0] = WrapTexCoord(br[0]);
79 : }
80 :
81 0 : if (tcr.y < 0 || tcr.y > aTexSize.height ||
82 0 : tcr.YMost() < 0 || tcr.YMost() > aTexSize.height)
83 : {
84 0 : ywrap = true;
85 0 : tl[1] = WrapTexCoord(tl[1]);
86 0 : br[1] = WrapTexCoord(br[1]);
87 : }
88 :
89 0 : NS_ASSERTION(tl[0] >= 0.0f && tl[0] <= 1.0f &&
90 : tl[1] >= 0.0f && tl[1] <= 1.0f &&
91 : br[0] >= 0.0f && br[0] <= 1.0f &&
92 : br[1] >= 0.0f && br[1] <= 1.0f,
93 : "Somehow generated invalid texture coordinates");
94 :
95 : // If xwrap is false, the texture will be sampled from tl[0]
96 : // .. br[0]. If xwrap is true, then it will be split into tl[0]
97 : // .. 1.0, and 0.0 .. br[0]. Same for the Y axis. The
98 : // destination rectangle is also split appropriately, according
99 : // to the calculated xmid/ymid values.
100 :
101 : // There isn't a 1:1 mapping between tex coords and destination coords;
102 : // when computing midpoints, we have to take that into account. We
103 : // need to map the texture coords, which are (in the wrap case):
104 : // |tl->1| and |0->br| to the |0->1| range of the vertex coords. So
105 : // we have the length (1-tl)+(br) that needs to map into 0->1.
106 : // These are only valid if there is wrap involved, they won't be used
107 : // otherwise.
108 0 : GLfloat xlen = (1.0f - tl[0]) + br[0];
109 0 : GLfloat ylen = (1.0f - tl[1]) + br[1];
110 :
111 0 : NS_ASSERTION(!xwrap || xlen > 0.0f, "xlen isn't > 0, what's going on?");
112 0 : NS_ASSERTION(!ywrap || ylen > 0.0f, "ylen isn't > 0, what's going on?");
113 0 : NS_ASSERTION(aTexCoordRect.width <= aTexSize.width &&
114 : aTexCoordRect.height <= aTexSize.height, "tex coord rect would cause tiling!");
115 :
116 0 : if (!xwrap && !ywrap) {
117 0 : aRects.addRect(0.0f, 0.0f,
118 : 1.0f, 1.0f,
119 : tl[0], tl[1],
120 : br[0], br[1],
121 0 : aFlipY);
122 0 : } else if (!xwrap && ywrap) {
123 0 : GLfloat ymid = (1.0f - tl[1]) / ylen;
124 0 : aRects.addRect(0.0f, 0.0f,
125 : 1.0f, ymid,
126 : tl[0], tl[1],
127 : br[0], 1.0f,
128 0 : aFlipY);
129 0 : aRects.addRect(0.0f, ymid,
130 : 1.0f, 1.0f,
131 : tl[0], 0.0f,
132 : br[0], br[1],
133 0 : aFlipY);
134 0 : } else if (xwrap && !ywrap) {
135 0 : GLfloat xmid = (1.0f - tl[0]) / xlen;
136 0 : aRects.addRect(0.0f, 0.0f,
137 : xmid, 1.0f,
138 : tl[0], tl[1],
139 : 1.0f, br[1],
140 0 : aFlipY);
141 0 : aRects.addRect(xmid, 0.0f,
142 : 1.0f, 1.0f,
143 : 0.0f, tl[1],
144 : br[0], br[1],
145 0 : aFlipY);
146 : } else {
147 0 : GLfloat xmid = (1.0f - tl[0]) / xlen;
148 0 : GLfloat ymid = (1.0f - tl[1]) / ylen;
149 0 : aRects.addRect(0.0f, 0.0f,
150 : xmid, ymid,
151 : tl[0], tl[1],
152 : 1.0f, 1.0f,
153 0 : aFlipY);
154 0 : aRects.addRect(xmid, 0.0f,
155 : 1.0f, ymid,
156 : 0.0f, tl[1],
157 : br[0], 1.0f,
158 0 : aFlipY);
159 0 : aRects.addRect(0.0f, ymid,
160 : xmid, 1.0f,
161 : tl[0], 0.0f,
162 : 1.0f, br[1],
163 0 : aFlipY);
164 0 : aRects.addRect(xmid, ymid,
165 : 1.0f, 1.0f,
166 : 0.0f, 0.0f,
167 : br[0], br[1],
168 0 : aFlipY);
169 : }
170 0 : }
171 :
172 : } // namespace gl
173 : } // namespace mozilla
|