View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host.dom;
16  
17  import org.htmlunit.corejs.javascript.Context;
18  import org.htmlunit.corejs.javascript.Function;
19  import org.htmlunit.corejs.javascript.Scriptable;
20  import org.htmlunit.javascript.configuration.JsxClass;
21  import org.htmlunit.javascript.configuration.JsxConstructor;
22  import org.htmlunit.javascript.configuration.JsxConstructorAlias;
23  import org.htmlunit.javascript.configuration.JsxFunction;
24  import org.htmlunit.javascript.configuration.JsxGetter;
25  import org.htmlunit.javascript.configuration.JsxSetter;
26  
27  /**
28   * A JavaScript object for {@code DOMMatrix}.
29   *
30   * @author Ahmed Ashour
31   * @author Ronald Brill
32   */
33  @JsxClass
34  public class DOMMatrix extends DOMMatrixReadOnly {
35  
36      /**
37       * JavaScript constructor.
38       * @param cx the current context
39       * @param scope the scope
40       * @param args the arguments to the WebSocket constructor
41       * @param ctorObj the function object
42       * @param inNewExpr Is new or not
43       * @return the java object to allow JavaScript to access
44       */
45      @JsxConstructor
46      @JsxConstructorAlias(alias = "WebKitCSSMatrix")
47      public static DOMMatrix jsConstructor(final Context cx, final Scriptable scope,
48              final Object[] args, final Function ctorObj, final boolean inNewExpr) {
49  
50          final DOMMatrix matrix = new DOMMatrix();
51          matrix.init(args, ctorObj);
52          return matrix;
53      }
54  
55      /**
56       * {@inheritDoc}
57       */
58      @Override
59      @JsxGetter
60      public double getM11() {
61          return super.getM11();
62      }
63  
64      /**
65       * {@inheritDoc}
66       */
67      @Override
68      @JsxSetter
69      public void setM11(final double m11) {
70          super.setM11(m11);
71      }
72  
73      /**
74       * {@inheritDoc}
75       */
76      @Override
77      @JsxGetter
78      public double getM12() {
79          return super.getM12();
80      }
81  
82      /**
83       * {@inheritDoc}
84       */
85      @Override
86      @JsxSetter
87      public void setM12(final double m12) {
88          super.setM12(m12);
89      }
90  
91      /**
92       * {@inheritDoc}
93       */
94      @Override
95      @JsxGetter
96      public double getM13() {
97          return super.getM13();
98      }
99  
100     /**
101      * {@inheritDoc}
102      */
103     @Override
104     @JsxSetter
105     public void setM13(final double m13) {
106         super.setM13(m13);
107     }
108 
109     /**
110      * {@inheritDoc}
111      */
112     @Override
113     @JsxGetter
114     public double getM14() {
115         return super.getM14();
116     }
117 
118     /**
119      * {@inheritDoc}
120      */
121     @Override
122     @JsxSetter
123     public void setM14(final double m14) {
124         super.setM14(m14);
125     }
126 
127     /**
128      * {@inheritDoc}
129      */
130     @Override
131     @JsxGetter
132     public double getM21() {
133         return super.getM21();
134     }
135 
136     /**
137      * {@inheritDoc}
138      */
139     @Override
140     @JsxSetter
141     public void setM21(final double m21) {
142         super.setM21(m21);
143     }
144 
145     /**
146      * {@inheritDoc}
147      */
148     @Override
149     @JsxGetter
150     public double getM22() {
151         return super.getM22();
152     }
153 
154     /**
155      * {@inheritDoc}
156      */
157     @Override
158     @JsxSetter
159     public void setM22(final double m22) {
160         super.setM22(m22);
161     }
162 
163     /**
164      * {@inheritDoc}
165      */
166     @Override
167     @JsxGetter
168     public double getM23() {
169         return super.getM23();
170     }
171 
172     /**
173      * {@inheritDoc}
174      */
175     @Override
176     @JsxSetter
177     public void setM23(final double m23) {
178         super.setM23(m23);
179     }
180 
181     /**
182      * {@inheritDoc}
183      */
184     @Override
185     @JsxGetter
186     public double getM24() {
187         return super.getM24();
188     }
189 
190     /**
191      * {@inheritDoc}
192      */
193     @Override
194     @JsxSetter
195     public void setM24(final double m24) {
196         super.setM24(m24);
197     }
198 
199     /**
200      * {@inheritDoc}
201      */
202     @Override
203     @JsxGetter
204     public double getM31() {
205         return super.getM31();
206     }
207 
208     /**
209      * {@inheritDoc}
210      */
211     @Override
212     @JsxSetter
213     public void setM31(final double m31) {
214         super.setM31(m31);
215     }
216 
217     /**
218      * {@inheritDoc}
219      */
220     @Override
221     @JsxGetter
222     public double getM32() {
223         return super.getM32();
224     }
225 
226     /**
227      * {@inheritDoc}
228      */
229     @Override
230     @JsxSetter
231     public void setM32(final double m32) {
232         super.setM32(m32);
233     }
234 
235     /**
236      * {@inheritDoc}
237      */
238     @Override
239     @JsxGetter
240     public double getM33() {
241         return super.getM33();
242     }
243 
244     /**
245      * {@inheritDoc}
246      */
247     @Override
248     @JsxSetter
249     public void setM33(final double m33) {
250         super.setM33(m33);
251     }
252 
253     /**
254      * {@inheritDoc}
255      */
256     @Override
257     @JsxGetter
258     public double getM34() {
259         return super.getM34();
260     }
261 
262     /**
263      * {@inheritDoc}
264      */
265     @Override
266     @JsxSetter
267     public void setM34(final double m34) {
268         super.setM34(m34);
269     }
270 
271     /**
272      * {@inheritDoc}
273      */
274     @Override
275     @JsxGetter
276     public double getM41() {
277         return super.getM41();
278     }
279 
280     /**
281      * {@inheritDoc}
282      */
283     @Override
284     @JsxSetter
285     public void setM41(final double m41) {
286         super.setM41(m41);
287     }
288 
289     /**
290      * {@inheritDoc}
291      */
292     @Override
293     @JsxGetter
294     public double getM42() {
295         return super.getM42();
296     }
297 
298     /**
299      * {@inheritDoc}
300      */
301     @Override
302     @JsxSetter
303     public void setM42(final double m42) {
304         super.setM42(m42);
305     }
306 
307     /**
308      * {@inheritDoc}
309      */
310     @Override
311     @JsxGetter
312     public double getM43() {
313         return super.getM43();
314     }
315 
316     /**
317      * {@inheritDoc}
318      */
319     @Override
320     @JsxSetter
321     public void setM43(final double m43) {
322         super.setM43(m43);
323     }
324 
325     /**
326      * {@inheritDoc}
327      */
328     @Override
329     @JsxGetter
330     public double getM44() {
331         return super.getM44();
332     }
333 
334     /**
335      * {@inheritDoc}
336      */
337     @Override
338     @JsxSetter
339     public void setM44(final double m44) {
340         super.setM44(m44);
341     }
342 
343     /**
344      * {@inheritDoc}
345      */
346     @Override
347     @JsxGetter
348     public double getA() {
349         return super.getA();
350     }
351 
352     /**
353      * @param a the new value
354      */
355     @JsxSetter
356     public void setA(final double a) {
357         super.setM11(a);
358     }
359 
360     /**
361      * {@inheritDoc}
362      */
363     @Override
364     @JsxGetter
365     public double getB() {
366         return super.getB();
367     }
368 
369     /**
370      * @param b the new value
371      */
372     @JsxSetter
373     public void setB(final double b) {
374         super.setM12(b);
375     }
376 
377     /**
378      * {@inheritDoc}
379      */
380     @Override
381     @JsxGetter
382     public double getC() {
383         return super.getC();
384     }
385 
386     /**
387      * @param c the new value
388      */
389     @JsxSetter
390     public void setC(final double c) {
391         super.setM21(c);
392     }
393 
394     /**
395      * {@inheritDoc}
396      */
397     @Override
398     @JsxGetter
399     public double getD() {
400         return super.getD();
401     }
402 
403     /**
404      * @param d the new value
405      */
406     @JsxSetter
407     public void setD(final double d) {
408         super.setM22(d);
409     }
410 
411     /**
412      * {@inheritDoc}
413      */
414     @Override
415     @JsxGetter
416     public double getE() {
417         return super.getE();
418     }
419 
420     /**
421      * @param e the new value
422      */
423     @JsxSetter
424     public void setE(final double e) {
425         super.setM41(e);
426     }
427 
428     /**
429      * {@inheritDoc}
430      */
431     @Override
432     @JsxGetter
433     public double getF() {
434         return super.getF();
435     }
436 
437     /**
438      * @param f the new value
439      */
440     @JsxSetter
441     public void setF(final double f) {
442         super.setM42(f);
443     }
444 
445     /**
446      * @return inverts the original matrix. If the matrix cannot be inverted,
447      *     the new matrix's components are all set to NaN and its is2D property is set to false.
448      */
449     @JsxFunction
450     public DOMMatrix invertSelf() {
451         if (isIs2D()) {
452             final double det = getM11() * getM22() - getM12() * getM21();
453             if (det == 0) {
454                 // Not invertible: set all to NaN, is2D_ = false
455                 initWithNan();
456                 return this;
457             }
458 
459             final double[] inv = new double[6];
460             inv[0] = getM22() / det;
461             inv[1] = -getM12() / det;
462 
463             inv[2] = -getM21() / det;
464             inv[3] = getM11() / det;
465 
466             inv[4] = (getM21() * getM42() - getM22() * getM41()) / det;
467             inv[5] = (getM12() * getM41() - getM11() * getM42()) / det;
468 
469             setM11(inv[0]);
470             setM12(inv[1]);
471             setM21(inv[2]);
472             setM22(inv[3]);
473             setM41(inv[4]);
474             setM42(inv[5]);
475             setIs2D(true);
476             return this;
477         }
478 
479         final double[] inv = new double[16];
480         inv[0] = getM22() * getM33() * getM44()
481                 - getM22() * getM34() * getM43()
482                 - getM32() * getM23() * getM44()
483                 + getM32() * getM24() * getM43()
484                 + getM42() * getM23() * getM34()
485                 - getM42() * getM24() * getM33();
486 
487         inv[4] = -getM21() * getM33() * getM44()
488                 + getM21() * getM34() * getM43()
489                 + getM31() * getM23() * getM44()
490                 - getM31() * getM24() * getM43()
491                 - getM41() * getM23() * getM34()
492                 + getM41() * getM24() * getM33();
493 
494         inv[8] = getM21() * getM32() * getM44()
495                 - getM21() * getM34() * getM42()
496                 - getM31() * getM22() * getM44()
497                 + getM31() * getM24() * getM42()
498                 + getM41() * getM22() * getM34()
499                 - getM41() * getM24() * getM32();
500 
501         inv[12] = -getM21() * getM32() * getM43()
502                 + getM21() * getM33() * getM42()
503                 + getM31() * getM22() * getM43()
504                 - getM31() * getM23() * getM42()
505                 - getM41() * getM22() * getM33()
506                 + getM41() * getM23() * getM32();
507 
508         inv[1] = -getM12() * getM33() * getM44()
509                 + getM12() * getM34() * getM43()
510                 + getM32() * getM13() * getM44()
511                 - getM32() * getM14() * getM43()
512                 - getM42() * getM13() * getM34()
513                 + getM42() * getM14() * getM33();
514 
515         inv[5] = getM11() * getM33() * getM44()
516                 - getM11() * getM34() * getM43()
517                 - getM31() * getM13() * getM44()
518                 + getM31() * getM14() * getM43()
519                 + getM41() * getM13() * getM34()
520                 - getM41() * getM14() * getM33();
521 
522         inv[9] = -getM11() * getM32() * getM44()
523                 + getM11() * getM34() * getM42()
524                 + getM31() * getM12() * getM44()
525                 - getM31() * getM14() * getM42()
526                 - getM41() * getM12() * getM34()
527                 + getM41() * getM14() * getM32();
528 
529         inv[13] = getM11() * getM32() * getM43()
530                 - getM11() * getM33() * getM42()
531                 - getM31() * getM12() * getM43()
532                 + getM31() * getM13() * getM42()
533                 + getM41() * getM12() * getM33()
534                 - getM41() * getM13() * getM32();
535 
536         inv[2] = getM12() * getM23() * getM44()
537                 - getM12() * getM24() * getM43()
538                 - getM22() * getM13() * getM44()
539                 + getM22() * getM14() * getM43()
540                 + getM42() * getM13() * getM24()
541                 - getM42() * getM14() * getM23();
542 
543         inv[6] = -getM11() * getM23() * getM44()
544                 + getM11() * getM24() * getM43()
545                 + getM21() * getM13() * getM44()
546                 - getM21() * getM14() * getM43()
547                 - getM41() * getM13() * getM24()
548                 + getM41() * getM14() * getM23();
549 
550         inv[10] = getM11() * getM22() * getM44()
551                 - getM11() * getM24() * getM42()
552                 - getM21() * getM12() * getM44()
553                 + getM21() * getM14() * getM42()
554                 + getM41() * getM12() * getM24()
555                 - getM41() * getM14() * getM22();
556 
557         inv[14] = -getM11() * getM22() * getM43()
558                 + getM11() * getM23() * getM42()
559                 + getM21() * getM12() * getM43()
560                 - getM21() * getM13() * getM42()
561                 - getM41() * getM12() * getM23()
562                 + getM41() * getM13() * getM22();
563 
564         inv[3] = -getM12() * getM23() * getM34()
565                 + getM12() * getM24() * getM33()
566                 + getM22() * getM13() * getM34()
567                 - getM22() * getM14() * getM33()
568                 - getM32() * getM13() * getM24()
569                 + getM32() * getM14() * getM23();
570 
571         inv[7] = getM11() * getM23() * getM34()
572                 - getM11() * getM24() * getM33()
573                 - getM21() * getM13() * getM34()
574                 + getM21() * getM14() * getM33()
575                 + getM31() * getM13() * getM24()
576                 - getM31() * getM14() * getM23();
577 
578         inv[11] = -getM11() * getM22() * getM34()
579                 + getM11() * getM24() * getM32()
580                 + getM21() * getM12() * getM34()
581                 - getM21() * getM14() * getM32()
582                 - getM31() * getM12() * getM24()
583                 + getM31() * getM14() * getM22();
584 
585         inv[15] = getM11() * getM22() * getM33()
586                 - getM11() * getM23() * getM32()
587                 - getM21() * getM12() * getM33()
588                 + getM21() * getM13() * getM32()
589                 + getM31() * getM12() * getM23()
590                 - getM31() * getM13() * getM22();
591 
592         double det = getM11() * inv[0] + getM12() * inv[4] + getM13() * inv[8] + getM14() * inv[12];
593 
594         if (det == 0) {
595             // Not invertible: set all to NaN, is2D_ = false
596             initWithNan();
597             return this;
598         }
599 
600         det = 1.0 / det;
601 
602         setM11(inv[0] * det);
603         setM12(inv[1] * det);
604         setM13(inv[2] * det);
605         setM14(inv[3] * det);
606 
607         setM21(inv[4] * det);
608         setM22(inv[5] * det);
609         setM23(inv[6] * det);
610         setM24(inv[7] * det);
611 
612         setM31(inv[8] * det);
613         setM32(inv[9] * det);
614         setM33(inv[10] * det);
615         setM34(inv[11] * det);
616 
617         setM41(inv[12] * det);
618         setM42(inv[13] * det);
619         setM43(inv[14] * det);
620         setM44(inv[15] * det);
621 
622         setIs2D(false);
623         return this;
624     }
625 
626     private void initWithNan() {
627         setM11(Double.NaN);
628         setM12(Double.NaN);
629         setM13(Double.NaN);
630         setM14(Double.NaN);
631         setM21(Double.NaN);
632         setM22(Double.NaN);
633         setM23(Double.NaN);
634         setM24(Double.NaN);
635         setM31(Double.NaN);
636         setM32(Double.NaN);
637         setM33(Double.NaN);
638         setM34(Double.NaN);
639         setM41(Double.NaN);
640         setM42(Double.NaN);
641         setM43(Double.NaN);
642         setM44(Double.NaN);
643         setIs2D(false);
644     }
645 }