Compare commits
763 Commits
matthiasc/
...
compile-ui
Author | SHA1 | Date | |
---|---|---|---|
|
7b68ef7669 | ||
|
11b9b1759a | ||
|
6474c7af35 | ||
|
145a16ff81 | ||
|
f079d75d1f | ||
|
e1facc548a | ||
|
87e4a542eb | ||
|
56e6a51ac0 | ||
|
da115ad075 | ||
|
4a89cfe2c9 | ||
|
c9135546b6 | ||
|
a94e438a29 | ||
|
164443a99a | ||
|
d88c4d122d | ||
|
d66bc501a4 | ||
|
1c2c356ed4 | ||
|
1fae91d123 | ||
|
24415a6ffb | ||
|
ae08aa3622 | ||
|
c24b7877a0 | ||
|
7b22e37371 | ||
|
c2ab1f172d | ||
|
136a3f6e5a | ||
|
2bc82da34d | ||
|
41b810da7f | ||
|
155e0f3dfb | ||
|
02bb23486f | ||
|
bc0d9488ee | ||
|
5742483422 | ||
|
7f2cb1138a | ||
|
1289e68931 | ||
|
9e6adaa913 | ||
|
9cfce67d0f | ||
|
295d406207 | ||
|
ece5fd7db5 | ||
|
c4e558da46 | ||
|
be1a60d5d0 | ||
|
a1adaac69b | ||
|
7e4b2b971f | ||
|
c6cacd2b2d | ||
|
2c8e55605b | ||
|
06db477847 | ||
|
e9cf8c6cc7 | ||
|
aad6b2d279 | ||
|
cf3830704b | ||
|
d962360fa0 | ||
|
76d31ff04b | ||
|
87af45403a | ||
|
15ffd49efb | ||
|
37a54eb9fc | ||
|
63647cace0 | ||
|
bef54a382d | ||
|
6a60214e8c | ||
|
27d662f1aa | ||
|
52a8492887 | ||
|
ba5d010e39 | ||
|
8c34dd58c0 | ||
|
0cce92ab19 | ||
|
f95c21b67c | ||
|
1d41dc716e | ||
|
3914ecbd0f | ||
|
0428d8ccd6 | ||
|
37a7c6780a | ||
|
1b85b5597b | ||
|
fae32846c7 | ||
|
b271a94f92 | ||
|
e58f70d7bb | ||
|
4fcf54757f | ||
|
b5da07f0e1 | ||
|
a85f4ec6c2 | ||
|
b226478e8b | ||
|
14280b5f5b | ||
|
e720f9d35d | ||
|
fecb31b706 | ||
|
729ad8e64a | ||
|
dcd873a6d8 | ||
|
679c93e843 | ||
|
2d3de8608c | ||
|
100b0bf7d9 | ||
|
f2ca9ebbd7 | ||
|
577bf104c0 | ||
|
b1bb7c3258 | ||
|
c77b5c46a3 | ||
|
5b82cf1145 | ||
|
95a0c93839 | ||
|
d27bc74481 | ||
|
e30b4c61cb | ||
|
daf29e174f | ||
|
729ba8111a | ||
|
d30a029689 | ||
|
945c2531ac | ||
|
f925e12e1d | ||
|
a03594df52 | ||
|
d7c8f92733 | ||
|
d6ce65f81c | ||
|
7949aaabb7 | ||
|
a71877bf99 | ||
|
f51f7f85eb | ||
|
66031fd00b | ||
|
698b3542a1 | ||
|
83ea623775 | ||
|
345faa7250 | ||
|
08df891070 | ||
|
56b31c3923 | ||
|
93323be22a | ||
|
9e14de2534 | ||
|
62954a0338 | ||
|
7cf5e5546b | ||
|
58f66ebd07 | ||
|
47330598fb | ||
|
90ed7b92b2 | ||
|
625b5ce91a | ||
|
c84d5b1f7f | ||
|
46bb160923 | ||
|
390a0b2f2a | ||
|
0dfab46c15 | ||
|
3a8ec683d3 | ||
|
de53b0c7a3 | ||
|
75dfb4d63b | ||
|
64acaf99fb | ||
|
551f76ea69 | ||
|
a4f3fbbda1 | ||
|
b6d3561f4a | ||
|
01944d57b7 | ||
|
c9aec9b5a2 | ||
|
025759e614 | ||
|
ed679703b8 | ||
|
fe46da1bf4 | ||
|
7fd8899092 | ||
|
9f8d6ff29c | ||
|
1230bce133 | ||
|
7c2be93a56 | ||
|
eb23e23b03 | ||
|
75b45aeabf | ||
|
23ffd6923d | ||
|
d2eb0288d9 | ||
|
a4b976f7a2 | ||
|
4930faa984 | ||
|
84fdda4f56 | ||
|
ec6228b3a4 | ||
|
8b85e7f35a | ||
|
d7909dccdc | ||
|
7773ae4538 | ||
|
bec44acdeb | ||
|
5bfac597f6 | ||
|
423a4d4c3e | ||
|
38fce67a9b | ||
|
04ef7055cd | ||
|
44a031c3c1 | ||
|
be885c888f | ||
|
6faef4416f | ||
|
5f452a5e6c | ||
|
060f2d5f65 | ||
|
ebca260f2d | ||
|
d4b1f85e14 | ||
|
4439ff0c12 | ||
|
ffab67ac70 | ||
|
0120ff3518 | ||
|
2e63b53b1e | ||
|
878c9da736 | ||
|
955d50a080 | ||
|
2b4f798e34 | ||
|
cda5d2dadd | ||
|
b664b2d1fd | ||
|
c70fdd6331 | ||
|
ddec3dedd0 | ||
|
b1a5c3ff55 | ||
|
8f9a5175f0 | ||
|
099c923679 | ||
|
2a12a3e6d9 | ||
|
cdc1fa166d | ||
|
f572ca52d2 | ||
|
193b383739 | ||
|
6785461c26 | ||
|
b9ee9979e7 | ||
|
6bbec87700 | ||
|
b35608a351 | ||
|
416763bf2d | ||
|
9179ebb28e | ||
|
bcc17b3033 | ||
|
00439f9e5c | ||
|
c9d748fc51 | ||
|
719eafa60c | ||
|
1759d27da9 | ||
|
53275481a5 | ||
|
cbe6d0da76 | ||
|
c349ed9562 | ||
|
74ce69a8a1 | ||
|
4f17f3ac24 | ||
|
9c8e464b04 | ||
|
51d0d13a9e | ||
|
0ee3b1c861 | ||
|
46f88c69a1 | ||
|
140976a670 | ||
|
9f2b847835 | ||
|
9e11ea699c | ||
|
1a4eebe022 | ||
|
2963468019 | ||
|
bfbd95d7d6 | ||
|
c1c1d4431d | ||
|
155a4fac5c | ||
|
76f481eb7b | ||
|
0782c8a051 | ||
|
3d27ff1177 | ||
|
3ada664a89 | ||
|
643a91bd08 | ||
|
c86733b4fa | ||
|
55099b7d0e | ||
|
db3858a204 | ||
|
07bff74544 | ||
|
b4262883a8 | ||
|
563c85e222 | ||
|
d75246a543 | ||
|
b3856a3ea0 | ||
|
bd4d24f8ed | ||
|
65ce3eb207 | ||
|
865ac44963 | ||
|
55a935db53 | ||
|
6fefae3dbb | ||
|
f7c84ddc7f | ||
|
f4a4dd2615 | ||
|
b718d99d1f | ||
|
c7215d1199 | ||
|
24d69ef125 | ||
|
7c3fbdecf2 | ||
|
b77938f40f | ||
|
f703744564 | ||
|
a3ccff3773 | ||
|
9869082c1c | ||
|
754212d0f9 | ||
|
a9b81577c6 | ||
|
eaa2dada54 | ||
|
ce2b2128bb | ||
|
41c25b8809 | ||
|
b5ff35ff3e | ||
|
06423d807f | ||
|
0395395d52 | ||
|
c3ca48b249 | ||
|
464e0aed04 | ||
|
d46e4fcecd | ||
|
363fb96e81 | ||
|
2382bd3bb2 | ||
|
3b0a9e84ab | ||
|
850aebea5d | ||
|
26e632e549 | ||
|
64d2d7074f | ||
|
062a15310a | ||
|
299c7c3514 | ||
|
6599cb001f | ||
|
f1347f5841 | ||
|
f3ccf62463 | ||
|
44fea33c5d | ||
|
8b48cf11f9 | ||
|
e681fdd958 | ||
|
d4b7a78c54 | ||
|
a45cbad553 | ||
|
16b9a30655 | ||
|
82a184a7b7 | ||
|
9e198a59b6 | ||
|
c002678085 | ||
|
486cffc361 | ||
|
67495fcc77 | ||
|
b26a370ce4 | ||
|
4dc0e67ac7 | ||
|
2c060663cf | ||
|
76a8eb4960 | ||
|
ad3dad1965 | ||
|
172d97de05 | ||
|
4c967d5b45 | ||
|
b244f31337 | ||
|
8550a04bf4 | ||
|
cb38ead48e | ||
|
9713c3394d | ||
|
fa57b006c9 | ||
|
9f73f0234a | ||
|
a4f067481c | ||
|
733fb527fa | ||
|
3667c6b053 | ||
|
1071818df8 | ||
|
11c2d9ea30 | ||
|
52cdf3056d | ||
|
32899a1edd | ||
|
119458f13e | ||
|
2863095f06 | ||
|
cbc050b9ed | ||
|
18affbd390 | ||
|
0b7a36ce33 | ||
|
1957915940 | ||
|
552b71d4e2 | ||
|
480112f9aa | ||
|
9a2f4d8026 | ||
|
3b15f32335 | ||
|
7404a6fc4f | ||
|
91d1ec41c2 | ||
|
9237c8be67 | ||
|
6c87d362c5 | ||
|
4f31d3587d | ||
|
29a2f4021a | ||
|
e2d321a16a | ||
|
7366f5099a | ||
|
4fbef5f466 | ||
|
2e48ff3362 | ||
|
7cdbdb663c | ||
|
1b390d3857 | ||
|
2808f9c75b | ||
|
49d109c29e | ||
|
36dd959bf9 | ||
|
2f9a67b8a1 | ||
|
6d5d9ea073 | ||
|
1cfd340cae | ||
|
369ccfc34f | ||
|
e556513de6 | ||
|
79dc1a2a4d | ||
|
9e5a501c73 | ||
|
2db8d7f6a2 | ||
|
94c3f4d4fc | ||
|
3fa26861cd | ||
|
ef2b0ccd6c | ||
|
f1702d24e7 | ||
|
3a50ff57d8 | ||
|
8ac2e8d495 | ||
|
e56cf85fd1 | ||
|
1c6aef1862 | ||
|
4653cbe56e | ||
|
93148d302f | ||
|
a443ba91ce | ||
|
d8daef2de7 | ||
|
845d43c77a | ||
|
f8dbcc472b | ||
|
0f0f75f6b1 | ||
|
4e2e2d84fc | ||
|
887885b6e0 | ||
|
a868a5c434 | ||
|
a0c147d246 | ||
|
38040c96d6 | ||
|
989ecf69ad | ||
|
9d26399143 | ||
|
b9cad7cc54 | ||
|
357b97b5a6 | ||
|
318160d836 | ||
|
5e90d63373 | ||
|
0b7f1e488f | ||
|
e281bbbb55 | ||
|
892bacee52 | ||
|
2f1db4b77c | ||
|
f90e9b26f8 | ||
|
ad71f454bd | ||
|
c66bd791c4 | ||
|
40bceef3ca | ||
|
9d79f55dc9 | ||
|
c5c1cf6d55 | ||
|
9eb8aa9a32 | ||
|
95931a7e6c | ||
|
d9daaed43f | ||
|
b9c51e65c1 | ||
|
da5eb92f47 | ||
|
03ed585f6f | ||
|
51f953a1aa | ||
|
93fb07d808 | ||
|
5e311d4d85 | ||
|
e652054d50 | ||
|
58c31b8627 | ||
|
b945033b41 | ||
|
92d2867170 | ||
|
5d38c8c558 | ||
|
552a4b2c82 | ||
|
7a4afb08bd | ||
|
c5cd1ac630 | ||
|
90edb76415 | ||
|
8f397502df | ||
|
1cb17d8613 | ||
|
88e796bb45 | ||
|
1310bf0218 | ||
|
4efeaa844f | ||
|
24685612a9 | ||
|
bf21df4195 | ||
|
417b3f9c6b | ||
|
2d84a1c63e | ||
|
5ab9a29bc4 | ||
|
383ea0d86a | ||
|
df8f75bb8f | ||
|
ba95ef63da | ||
|
bea4aa31ea | ||
|
6c19a8352f | ||
|
e3df89b524 | ||
|
a9003f7ac0 | ||
|
2cc06f60c5 | ||
|
4759afcc3e | ||
|
66b297e408 | ||
|
bbd2b255a3 | ||
|
8b2f28eee3 | ||
|
ae767dc5bf | ||
|
d923402934 | ||
|
9667f889b3 | ||
|
d2ea7af335 | ||
|
f95e9407a9 | ||
|
7be3c2974a | ||
|
5444f604cb | ||
|
94e68b0e36 | ||
|
910d86f958 | ||
|
fd885e42b0 | ||
|
ea31ae31c1 | ||
|
00763e5af3 | ||
|
1bf5aab18c | ||
|
210a709246 | ||
|
5feba67a3d | ||
|
e9e373913e | ||
|
f1f197e3b9 | ||
|
cedb6183e9 | ||
|
0415d46c0f | ||
|
68388331c7 | ||
|
92817b0603 | ||
|
f8a1726ffa | ||
|
be34f27026 | ||
|
12c5518e2b | ||
|
d8ab5c3c45 | ||
|
36d1c9e8b7 | ||
|
45c047f5c0 | ||
|
da1232caaf | ||
|
fff5a83957 | ||
|
f5b6488eb2 | ||
|
c02bae9e08 | ||
|
58e65ae7dd | ||
|
3977518f00 | ||
|
8adee3dace | ||
|
09ad930da4 | ||
|
52f7bb6950 | ||
|
68db945e47 | ||
|
b54f4cf5d4 | ||
|
9a8a9451b1 | ||
|
fffa903ce9 | ||
|
ab08885a32 | ||
|
ad3995b1b9 | ||
|
75cc0710ac | ||
|
7cec7054e2 | ||
|
fe280e578f | ||
|
a32973f56b | ||
|
7762311911 | ||
|
edd73ffbed | ||
|
fca87d93e9 | ||
|
c2fe2c0385 | ||
|
8aa25046dc | ||
|
27a07ed89c | ||
|
071a6bcc06 | ||
|
f98ac6590d | ||
|
6b733d2943 | ||
|
6f165efcdb | ||
|
7bc1c9a562 | ||
|
1596fdeba3 | ||
|
1599b659cf | ||
|
bb65564c7d | ||
|
03031b3dc1 | ||
|
b7636ebbc0 | ||
|
5707b80a69 | ||
|
81e5d4c327 | ||
|
f8111125ef | ||
|
c020e83890 | ||
|
f6659fea8d | ||
|
a06858ccd9 | ||
|
c6c48d327c | ||
|
5d0f188615 | ||
|
78fcc8feb8 | ||
|
27cad85247 | ||
|
ad0c1d4dbe | ||
|
00abaed89a | ||
|
342f02711b | ||
|
d9c48a8d01 | ||
|
d757696116 | ||
|
528ebfabf0 | ||
|
2ebde276d1 | ||
|
04f3c8054b | ||
|
ea07bf7536 | ||
|
80e6f1ca8c | ||
|
54d29568ec | ||
|
4e1ea58503 | ||
|
90c429a91c | ||
|
4b28e038e0 | ||
|
8df694a358 | ||
|
eb8778e1cd | ||
|
256f3a0d60 | ||
|
54c087e7ec | ||
|
69a99b89f9 | ||
|
f328ab9d83 | ||
|
8acce5f294 | ||
|
bdbe0acd1f | ||
|
fc701baef8 | ||
|
a457a81fd9 | ||
|
4cc7977d36 | ||
|
e5e7f5dd88 | ||
|
916886312a | ||
|
8ff94ea1f2 | ||
|
053bd0cd31 | ||
|
a3ce574193 | ||
|
ef92adc87d | ||
|
46a9538b6a | ||
|
ca547b8716 | ||
|
04ea51e843 | ||
|
f7dc0dda4e | ||
|
8713843022 | ||
|
6563b05d60 | ||
|
d119c55b72 | ||
|
253e25a73c | ||
|
c63774967f | ||
|
bbc36448fb | ||
|
5df323fb64 | ||
|
0f2c5f13be | ||
|
58180ad3be | ||
|
fb0229890b | ||
|
9099888398 | ||
|
882855f865 | ||
|
f59d2ae89d | ||
|
7c3a53a171 | ||
|
1e22572716 | ||
|
8a25f54e1f | ||
|
c51f2fc0ec | ||
|
2a528df977 | ||
|
84684bd56e | ||
|
e1606ce8eb | ||
|
47072e0441 | ||
|
915c229396 | ||
|
0bf46b4845 | ||
|
a7a2dbc3ea | ||
|
7e8f586859 | ||
|
bb9dccd773 | ||
|
7b743e662e | ||
|
769dc53c05 | ||
|
1a4554daf3 | ||
|
6c0633ef61 | ||
|
4d020a3875 | ||
|
316cc55e69 | ||
|
95f2634ea9 | ||
|
95c032f531 | ||
|
744955753f | ||
|
ae5e7dc65d | ||
|
ed41c46926 | ||
|
a460fb2734 | ||
|
39ddce6ba3 | ||
|
8da7e3bdc3 | ||
|
eff53c023a | ||
|
99e4a6a2d6 | ||
|
c06817b951 | ||
|
e765aaa3f4 | ||
|
1728aa581c | ||
|
c50475de34 | ||
|
5d7ecb7a6e | ||
|
06348a8517 | ||
|
c4dbb8f01e | ||
|
e67b2cb54b | ||
|
908b1e5e12 | ||
|
539391ce6c | ||
|
7fc90aed26 | ||
|
23e79d2eb2 | ||
|
0c7b1431d7 | ||
|
b6c0155836 | ||
|
76d67b586c | ||
|
914edb1472 | ||
|
dbf5033f94 | ||
|
cc6ecc8b62 | ||
|
b7e6922605 | ||
|
05eaffb9f2 | ||
|
67b568f464 | ||
|
19b534f7de | ||
|
bc386c9a60 | ||
|
db8b3419c2 | ||
|
0f5ba5192a | ||
|
108c423d70 | ||
|
dded10a396 | ||
|
1b080826db | ||
|
910f23ea19 | ||
|
f1b50baba1 | ||
|
4453597946 | ||
|
192bfa10cb | ||
|
0781429dc5 | ||
|
d760332f00 | ||
|
131be5f2e8 | ||
|
57a95c540c | ||
|
09deb1d757 | ||
|
5c4aba4b9c | ||
|
6a5d555f58 | ||
|
f5dc71021f | ||
|
39005461c5 | ||
|
4dc4c00267 | ||
|
d76460343a | ||
|
0d8dd0c664 | ||
|
ee6491f717 | ||
|
7044951dab | ||
|
98986a25f9 | ||
|
ae3e586714 | ||
|
0ef12193f9 | ||
|
b695ef9168 | ||
|
7fb1389648 | ||
|
f88efb811b | ||
|
466d33ca69 | ||
|
d44ce1987d | ||
|
527b2c5ab1 | ||
|
4d0c2997cf | ||
|
6f04ec9dae | ||
|
00cc99818d | ||
|
e51fdc1c9b | ||
|
8d5ef4ab30 | ||
|
7bdda15b86 | ||
|
4c41ef8de3 | ||
|
7aec3b0fa1 | ||
|
fce23c981b | ||
|
351819b570 | ||
|
a10b1b7341 | ||
|
02c6226741 | ||
|
620ccdabb5 | ||
|
4b12dc6547 | ||
|
bd69d7e23f | ||
|
8648486400 | ||
|
6c00117119 | ||
|
9c4c4eaaa1 | ||
|
969b3257a7 | ||
|
65c6af31e1 | ||
|
6b8bc83420 | ||
|
30aaab5c6c | ||
|
72e2a46c05 | ||
|
e06e0e8555 | ||
|
9f1d6e1f44 | ||
|
15ed1a329e | ||
|
505436340b | ||
|
a27434a8a7 | ||
|
2c987861a6 | ||
|
c7320df0c9 | ||
|
dd666e4fe4 | ||
|
e4f0418003 | ||
|
430b6f8fb1 | ||
|
ba3e80cbfa | ||
|
7cd4282bad | ||
|
01e9fa9adb | ||
|
581e01b2da | ||
|
5a3b4de1b7 | ||
|
74288eceaf | ||
|
37ba057128 | ||
|
6d5ba9590b | ||
|
215f792851 | ||
|
1c55b32879 | ||
|
82eb947f41 | ||
|
485dae9f25 | ||
|
eb3423312f | ||
|
04c2093d5c | ||
|
ccd5992a83 | ||
|
ca8d9fbe0b | ||
|
62bac44a21 | ||
|
0ddd06113d | ||
|
b1fbc2ef24 | ||
|
c787fe7ecb | ||
|
bdb49720be | ||
|
1d448a2b8a | ||
|
c5df081904 | ||
|
8a2f3e1fe5 | ||
|
8dfc627e46 | ||
|
0fce30070f | ||
|
8bfe82f686 | ||
|
7d32ec51e7 | ||
|
5784f8c2f9 | ||
|
74e01ddec5 | ||
|
1347573139 | ||
|
f2b41e708d | ||
|
a5555943ed | ||
|
2c023cdaed | ||
|
bcc7028640 | ||
|
bdee75cd0f | ||
|
94eb3d7ac0 | ||
|
0ae2acfb1a | ||
|
afc5f46ca9 | ||
|
e544c891ca | ||
|
af0c95c11a | ||
|
4d5dc18a57 | ||
|
9f6fb161e2 | ||
|
3883a98771 | ||
|
9b44965f13 | ||
|
aa6a9de6ba | ||
|
8669e8a498 | ||
|
ead31db096 | ||
|
69fda941c7 | ||
|
67c9e7a4a8 | ||
|
4e4f57e091 | ||
|
ac64d2d910 | ||
|
49a76257cd | ||
|
77829cf3ed | ||
|
4d10ab3d35 | ||
|
e609ede597 | ||
|
2ba69abe39 | ||
|
a76f515569 | ||
|
a663b8c313 | ||
|
f66fa16bd1 | ||
|
8390363abe | ||
|
6ff85d287a | ||
|
94c2072be8 | ||
|
64b9d53472 | ||
|
a5e7b92c5d | ||
|
2da9ba63e2 | ||
|
5d02a8f5db | ||
|
834d3749c6 | ||
|
1c90bb522e | ||
|
b70b058b66 | ||
|
b99beeb552 | ||
|
c799452973 | ||
|
fd48afb77d | ||
|
aaa68954c3 | ||
|
433233258b | ||
|
3eed61deba | ||
|
87e2a02e0c | ||
|
264d592012 | ||
|
0ad5094119 | ||
|
67952a9142 | ||
|
ca3d942b9b | ||
|
5470a1344d | ||
|
4390f8102b | ||
|
92129a2011 | ||
|
54dffa07f3 | ||
|
1cff4bb27a | ||
|
8087250476 | ||
|
485dc052ca | ||
|
45d39c2802 | ||
|
3b4b1c6878 | ||
|
ff4f07d76f | ||
|
fb6c8cd466 | ||
|
8464b0484f | ||
|
bee58fd09d | ||
|
d25557a5ef | ||
|
da3ca6604b | ||
|
74cba6c3b2 | ||
|
c09718b731 | ||
|
eacfa2a966 | ||
|
e7f228e240 | ||
|
fab82a7c25 | ||
|
fc9c34897a | ||
|
28cdd3f497 | ||
|
a009e26e95 | ||
|
ab908c23f4 | ||
|
ae21f66fe5 | ||
|
2d092ea280 | ||
|
0f9d39cdfd | ||
|
a64087d481 | ||
|
c85f3f4942 | ||
|
d7553279ff | ||
|
c86631b8a9 | ||
|
c1af63de9b | ||
|
2784b03b2d | ||
|
10bdf8c645 | ||
|
d63d9b2319 | ||
|
d5f2b69d0c | ||
|
6818eee859 | ||
|
e7f1398d85 | ||
|
880c01f8cc | ||
|
337c5e5e59 | ||
|
af52ea78c6 | ||
|
fe633d9ef9 | ||
|
e6cce283a7 | ||
|
c920236c54 | ||
|
6f86b4d220 | ||
|
a085e174c5 | ||
|
d3c08789a3 | ||
|
630488210b | ||
|
873f6ccfea | ||
|
af15f5d004 | ||
|
f328175e2f | ||
|
fc65d6393a | ||
|
271afb7eab | ||
|
76133dbea7 |
@@ -7,6 +7,7 @@ stages:
|
||||
- analysis
|
||||
- docs
|
||||
- flatpak
|
||||
- publish
|
||||
- deploy
|
||||
|
||||
.cache-paths: &cache-paths
|
||||
@@ -24,7 +25,7 @@ variables:
|
||||
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
|
||||
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled"
|
||||
MESON_TEST_TIMEOUT_MULTIPLIER: 3
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v32"
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v34"
|
||||
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
|
||||
|
||||
.only-default:
|
||||
@@ -57,6 +58,7 @@ style-check-diff:
|
||||
- "${CI_PROJECT_DIR}/_build/report*.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/report*.html"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*/*.png"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/tools/output/*/*"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*/*.png"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/css/output/*/*.syscap"
|
||||
- "${CI_PROJECT_DIR}/_build_hello/meson-logs"
|
||||
@@ -172,6 +174,7 @@ macos:
|
||||
- meson -Dx11-backend=false
|
||||
-Dbroadway-backend=true
|
||||
-Dmacos-backend=true
|
||||
-Dmedia-gstreamer=disabled
|
||||
-Dintrospection=disabled
|
||||
-Dcpp_std=c++11
|
||||
-Dpixman:tests=disabled
|
||||
@@ -335,14 +338,11 @@ reference:
|
||||
paths:
|
||||
- _reference
|
||||
|
||||
pages:
|
||||
stage: deploy
|
||||
publish-docs:
|
||||
stage: publish
|
||||
needs: ['reference']
|
||||
script:
|
||||
- mv _reference/ public/
|
||||
- cp .gitlab-ci/pages/* public/
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
- "curl -X POST -F token=${PAGES_TRIGGER_TOKEN} -F ref=docs-gtk-org https://gitlab.gnome.org/api/v4/projects/665/trigger/pipeline"
|
||||
only:
|
||||
- master
|
||||
refs:
|
||||
- master
|
||||
|
@@ -48,9 +48,12 @@ RUN dnf -y install \
|
||||
libcloudproviders-devel \
|
||||
libepoxy-devel \
|
||||
libffi-devel \
|
||||
libjpeg-turbo-devel \
|
||||
libmount-devel \
|
||||
libpng-devel \
|
||||
librsvg2 \
|
||||
libselinux-devel \
|
||||
libtiff-devel \
|
||||
libubsan \
|
||||
libXcomposite-devel \
|
||||
libXcursor-devel \
|
||||
|
@@ -15,7 +15,7 @@ meson \
|
||||
-Dx11-backend=true \
|
||||
-Dwayland-backend=true \
|
||||
-Dbroadway-backend=true \
|
||||
-Dvulkan=yes \
|
||||
-Dvulkan=enabled \
|
||||
-Dprofiler=true \
|
||||
--werror \
|
||||
${EXTRA_MESON_FLAGS:-} \
|
||||
|
@@ -6,7 +6,7 @@ call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliar
|
||||
|
||||
:: FIXME: make warnings fatal
|
||||
pip3 install --upgrade --user meson==0.56.2 || goto :error
|
||||
meson _build || goto :error
|
||||
meson -Dmedia-gstreamer=disabled _build || goto :error
|
||||
ninja -C _build || goto :error
|
||||
|
||||
goto :EOF
|
||||
|
@@ -40,7 +40,7 @@ export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
|
||||
# https://gitlab.gnome.org/GNOME/gtk/-/issues/2243
|
||||
# https://gitlab.gnome.org/GNOME/gtk/-/issues/3002
|
||||
|
||||
if ! pkg-config --atleast-version=2.65.0 glib-2.0; then
|
||||
if ! pkg-config --atleast-version=2.66.0 glib-2.0; then
|
||||
git clone https://gitlab.gnome.org/GNOME/glib.git _glib
|
||||
meson setup _glib_build _glib
|
||||
meson compile -C _glib_build
|
||||
@@ -48,7 +48,7 @@ if ! pkg-config --atleast-version=2.65.0 glib-2.0; then
|
||||
fi
|
||||
pkg-config --modversion glib-2.0
|
||||
|
||||
if ! pkg-config --atleast-version=1.47.0 pango; then
|
||||
if ! pkg-config --atleast-version=1.49.1 pango; then
|
||||
git clone https://gitlab.gnome.org/GNOME/pango.git _pango
|
||||
meson setup _pango_build _pango
|
||||
meson compile -C _pango_build
|
||||
|
188
NEWS
188
NEWS
@@ -1,3 +1,191 @@
|
||||
Overview of Changes
|
||||
===================
|
||||
|
||||
* gsk:
|
||||
- Drop the GL renderer in favor of NGL
|
||||
|
||||
* css:
|
||||
- Add support for line-height
|
||||
- Add support for text-transform
|
||||
|
||||
* GtkTextView:
|
||||
- Add support for line height
|
||||
- Add support for text transforms
|
||||
|
||||
* Build:
|
||||
- Require Pango 1.49
|
||||
|
||||
|
||||
Overview of Changes in 4.4.0
|
||||
============================
|
||||
|
||||
* Input:
|
||||
- Match IBus for display of Compose sequences
|
||||
- Match IBus for handling of mismatches
|
||||
- Handle Escape in Compose sequences
|
||||
- Allow multiple dead keys
|
||||
- Support 32bit keysyms
|
||||
|
||||
* GtkCheckButton:
|
||||
- Activate when moving focus
|
||||
|
||||
* GtkLabel:
|
||||
- Propertly ignore double underscores for mnemonics
|
||||
|
||||
* GtkPopoverMenu:
|
||||
- Fix focus cycling
|
||||
|
||||
* GtkTextView:
|
||||
- Improve word selection
|
||||
- Fix block cursors on empty lines
|
||||
|
||||
* GdkToplevel:
|
||||
- Support the gnome-shell titlebar gesture protocol
|
||||
|
||||
* GdkDropTarget:
|
||||
- Allow creating drop targets in ui files
|
||||
|
||||
* gsk:
|
||||
- Handle partial color fonts correctly
|
||||
- Use harfbuzz for color font information
|
||||
- Avoid pango for glyph cache rendering
|
||||
- Shrink shadow extents
|
||||
|
||||
* Settings:
|
||||
- Change the default for gtk-split-cursor to FALSE
|
||||
|
||||
* Demos:
|
||||
- Small improvements to widget-factory
|
||||
- gtk-demo: Improve the hypertext demo
|
||||
- gtk-dem: Improve the clipboard demo
|
||||
|
||||
* X11:
|
||||
- Set WM_CLASS on toplevels
|
||||
|
||||
* Wayland:
|
||||
- Support wl_seat v7
|
||||
|
||||
* Windows:
|
||||
- Drop the local DND protocol
|
||||
- Avoid WGL if shaders don't work
|
||||
- Use WinPointer API
|
||||
|
||||
* Translation updates:
|
||||
Belarusian
|
||||
Friulian
|
||||
Hebrew
|
||||
Khmer
|
||||
Persian
|
||||
Polish
|
||||
|
||||
|
||||
Overview of Changes in 4.3.2
|
||||
============================
|
||||
|
||||
* GtkToggleButton:
|
||||
- Fix the actionable implementation
|
||||
|
||||
* GtkCheckButton:
|
||||
- Fix the actionable implementation
|
||||
- Cancel activation on when the pointer leaves
|
||||
|
||||
* GtkMenuButton:
|
||||
- Make activatable again
|
||||
- Add a way to have an icon + arrow
|
||||
|
||||
* GtkColorButton:
|
||||
- Make activatable again
|
||||
|
||||
* GtkFontButton:
|
||||
- Make activatable again
|
||||
|
||||
* GtkAppChooserButton:
|
||||
- Make activatable again
|
||||
|
||||
* GtkColumnView:
|
||||
- Fix double activation
|
||||
|
||||
* GtkLabel:
|
||||
- Fix mnemonics without markup
|
||||
|
||||
* GtkTreeView:
|
||||
- Clip header buttons
|
||||
|
||||
* GtkTextView:
|
||||
- Add api to get the RTL and LTR contexts
|
||||
- Fix some errors in text history grouping
|
||||
|
||||
* GtkText:
|
||||
- Don't show placeholder text on top of entry text
|
||||
- Add api to compute the cursor extents
|
||||
- Fix y coordinates for text selection
|
||||
|
||||
* GtkFileChooser:
|
||||
- Don't show Trash in the side bar
|
||||
|
||||
* GtkPopoverMenu:
|
||||
- Add scrollbars to long menus
|
||||
|
||||
* GtkActionMuxer:
|
||||
- Fix propagation of accel changes
|
||||
|
||||
* Introspection:
|
||||
- Annotate all filename arguments
|
||||
- Rename GtkMediaStream apis to avoid name collisions
|
||||
- Rename GtkDropTarget properties to avoid name collisions
|
||||
- Make GtkPasswordEntryBuffer introspectable
|
||||
|
||||
* Printing:
|
||||
- Remove the Google Cloud Print backend
|
||||
|
||||
* Theme:
|
||||
- Sync included icons with the Adwaita icon theme
|
||||
|
||||
* GSK:
|
||||
- Avoid overflowing the vertex counter
|
||||
- Handle negative scales correctly in the ngl renderer
|
||||
|
||||
* GDK:
|
||||
- Cleanup and simplify OpenGL setup code
|
||||
- Add a GdkDisplay::init_gl vfunc and gdk_display_prepare_gl() api
|
||||
- Require EGL 1.4
|
||||
- Fix EGL + NVidia
|
||||
|
||||
* Build:
|
||||
- Enable gstreamer by default
|
||||
- Disable Vulkan by default
|
||||
- Remove the sassc option
|
||||
- Remove options and checks for X11 extensions
|
||||
|
||||
* X11:
|
||||
- Stop using XComposite
|
||||
- Remove the Visual cache
|
||||
|
||||
* Wayland:
|
||||
- Fix some DND corner cases
|
||||
- Work with version 2 of pointer-gestures-v1
|
||||
- Look for cursor themes in $HOME/.icons
|
||||
|
||||
* Windows:
|
||||
- Fix SIGILL on x64 due to popcnt
|
||||
- Fix popup placement
|
||||
- Fix drag icon placement
|
||||
- Clean up HiDPI and WGL support
|
||||
- Default to WGL
|
||||
|
||||
* MacOs:
|
||||
- Fix input method support
|
||||
- Register known clipboard types for drop targets
|
||||
- Add initial DND support
|
||||
|
||||
* Translation updates:
|
||||
Brazilian Portuguese
|
||||
Portuguese
|
||||
Romanian
|
||||
Turkish
|
||||
Ukrainian
|
||||
|
||||
|
||||
Overview of Changes in 4.3.1
|
||||
============================
|
||||
|
||||
|
13
README.md
13
README.md
@@ -10,10 +10,12 @@ GTK is a multi-platform toolkit for creating graphical user interfaces.
|
||||
Offering a complete set of widgets, GTK is suitable for projects ranging
|
||||
from small one-off projects to complete application suites.
|
||||
|
||||
GTK is free software and part of the GNU Project. However, the
|
||||
licensing terms for GTK, the GNU LGPL, allow it to be used by all
|
||||
developers, including those developing proprietary software, without any
|
||||
license fees or royalties.
|
||||
GTK is a free and open-source software project. The licensing terms
|
||||
for GTK, the GNU LGPL, allow it to be used by all developers, including those
|
||||
developing proprietary software, without any license fees or royalties.
|
||||
|
||||
GTK is hosted by the GNOME project (thanks!) and used by a wide variety
|
||||
of applications and projects.
|
||||
|
||||
The official download location
|
||||
|
||||
@@ -151,6 +153,9 @@ Contributing to GTK
|
||||
Please, follow the [contribution guide](./CONTRIBUTING.md) to know how to
|
||||
start contributing to GTK.
|
||||
|
||||
If you want to support GTK financially, please consider donating to
|
||||
the GNOME project, which runs the infrastructure hosting GTK.
|
||||
|
||||
Release notes
|
||||
-------------
|
||||
|
||||
|
289
config.h.meson
289
config.h.meson
@@ -1,289 +0,0 @@
|
||||
/* always defined to indicate that i18n is enabled */
|
||||
#define ENABLE_NLS 1
|
||||
|
||||
/* Use structured logging */
|
||||
#define G_LOG_STRUCTURED 1
|
||||
|
||||
/* The prefix for our gettext translation domains. */
|
||||
#mesondefine GETTEXT_PACKAGE
|
||||
|
||||
/* Disable deprecation warnings from glib */
|
||||
#mesondefine GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
/* Define the location where the catalogs will be installed */
|
||||
#mesondefine GTK_LOCALEDIR
|
||||
|
||||
/* Define to 1 if you have the `bind_textdomain_codeset' function. */
|
||||
#mesondefine HAVE_BIND_TEXTDOMAIN_CODESET
|
||||
|
||||
/* Have the cloudproviders library */
|
||||
#mesondefine HAVE_CLOUDPROVIDERS
|
||||
|
||||
/* define if we have colord */
|
||||
#mesondefine HAVE_COLORD
|
||||
|
||||
/* Define to 1 if you have the <crt_externs.h> header file. */
|
||||
#mesondefine HAVE_CRT_EXTERNS_H
|
||||
|
||||
/* Define to 1 if you have the `dcgettext' function. */
|
||||
#mesondefine HAVE_DCGETTEXT
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#mesondefine HAVE_DLFCN_H
|
||||
|
||||
/* Have the ffmpeg library */
|
||||
#mesondefine HAVE_FFMPEG
|
||||
|
||||
/* Define to 1 if you have the <ftw.h> header file. */
|
||||
#mesondefine HAVE_FTW_H
|
||||
|
||||
/* Define to 1 if you have the `getpagesize' function. */
|
||||
#mesondefine HAVE_GETPAGESIZE
|
||||
|
||||
/* Define to 1 if you have the `getresuid' function. */
|
||||
#mesondefine HAVE_GETRESUID
|
||||
|
||||
/* Define if gio-unix is available */
|
||||
#mesondefine HAVE_GIO_UNIX
|
||||
|
||||
/* Define if GStreamer support is available */
|
||||
#mesondefine HAVE_GSTREAMER
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#mesondefine HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if the system has the type `IPrintDialogCallback'. */
|
||||
#mesondefine HAVE_IPRINTDIALOGCALLBACK
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#mesondefine HAVE_LOCALE_H
|
||||
|
||||
/* Define to 1 if you have the `lstat' function. */
|
||||
#mesondefine HAVE_LSTAT
|
||||
|
||||
/* Define to 1 if you have the `mallinfo' function. */
|
||||
#mesondefine HAVE_MALLINFO
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#mesondefine HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `mkstemp' function. */
|
||||
#mesondefine HAVE_MKSTEMP
|
||||
|
||||
/* Define to 1 if you have the `mlock` function. */
|
||||
#mesondefine HAVE_MLOCK
|
||||
|
||||
/* Define to 1 if you have a working `mmap' system call. */
|
||||
#mesondefine HAVE_MMAP
|
||||
|
||||
/* Define to 1 if you have a working `madvise' system call. */
|
||||
#mesondefine HAVE_MADVISE
|
||||
|
||||
/* Define to 1 if you have the `posix_fallocate' function. */
|
||||
#mesondefine HAVE_POSIX_FALLOCATE
|
||||
|
||||
/* Have the Xrandr extension library */
|
||||
#mesondefine HAVE_RANDR
|
||||
|
||||
/* Have the Xrandr 1.5 extension library */
|
||||
#mesondefine HAVE_RANDR15
|
||||
|
||||
/* Define to 1 if you have the `sincos' function. */
|
||||
#mesondefine HAVE_SINCOS
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#mesondefine HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#mesondefine HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#mesondefine HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#mesondefine HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/mman.h> header file. */
|
||||
#mesondefine HAVE_SYS_MMAN_H
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#mesondefine HAVE_SYS_PARAM_H
|
||||
|
||||
/* Have the sysprof-capture library */
|
||||
#mesondefine HAVE_SYSPROF
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#mesondefine HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#mesondefine HAVE_SYS_TIME_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#mesondefine HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#mesondefine HAVE_UNISTD_H
|
||||
|
||||
/* Have the XCOMPOSITE X extension */
|
||||
#mesondefine HAVE_XCOMPOSITE
|
||||
|
||||
/* Have the Xcursor library */
|
||||
#mesondefine HAVE_XCURSOR
|
||||
|
||||
/* Have the XDAMAGE X extension */
|
||||
#mesondefine HAVE_XDAMAGE
|
||||
|
||||
/* Have the XFIXES X extension */
|
||||
#mesondefine HAVE_XFIXES
|
||||
|
||||
/* Define to 1 if XFree Xinerama is available */
|
||||
#mesondefine HAVE_XFREE_XINERAMA
|
||||
|
||||
/* Have XGenericEvent */
|
||||
#mesondefine HAVE_XGENERICEVENTS
|
||||
|
||||
/* Define to use XKB extension */
|
||||
#mesondefine HAVE_XKB
|
||||
|
||||
/* Have the SYNC extension library */
|
||||
#mesondefine HAVE_XSYNC
|
||||
|
||||
/* Define to 1 if you have the `_lock_file' function */
|
||||
#mesondefine HAVE__LOCK_FILE
|
||||
|
||||
/* Define to 1 if you have the `flockfile' function */
|
||||
#mesondefine HAVE_FLOCKFILE
|
||||
|
||||
/* Define if _NL_MEASUREMENT_MEASUREMENT is available */
|
||||
#mesondefine HAVE__NL_MEASUREMENT_MEASUREMENT
|
||||
|
||||
/* Define if _NL_PAPER_HEIGHT is available */
|
||||
#mesondefine HAVE__NL_PAPER_HEIGHT
|
||||
|
||||
/* Define if _NL_PAPER_WIDTH is available */
|
||||
#mesondefine HAVE__NL_PAPER_WIDTH
|
||||
|
||||
/* Define if _NL_TIME_FIRST_WEEKDAY is available */
|
||||
#mesondefine HAVE__NL_TIME_FIRST_WEEKDAY
|
||||
|
||||
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||
#mesondefine LT_OBJDIR
|
||||
|
||||
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
|
||||
#mesondefine NO_MINUS_C_MINUS_O
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#mesondefine PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#mesondefine PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#mesondefine PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#mesondefine PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#mesondefine PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#mesondefine PACKAGE_VERSION
|
||||
|
||||
/* Use NSBundle functions to determine load paths for libraries, translations,
|
||||
etc. */
|
||||
#mesondefine QUARTZ_RELOCATION
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#mesondefine STDC_HEADERS
|
||||
|
||||
/* Enable extensions on AIX 3, Interix. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# undef _GNU_SOURCE
|
||||
#endif
|
||||
/* Enable threading extensions on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# undef _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# undef _TANDEM_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
#endif
|
||||
|
||||
|
||||
/* Define to 1 if XInput 2.2 is available */
|
||||
#mesondefine XINPUT_2_2
|
||||
|
||||
/* Define to 1 if the X Window System is missing or not being used. */
|
||||
#mesondefine X_DISPLAY_MISSING
|
||||
|
||||
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
#endif
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#mesondefine _FILE_OFFSET_BITS
|
||||
|
||||
/* defines how to decorate public symbols while building */
|
||||
#mesondefine _GDK_EXTERN
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#mesondefine _LARGE_FILES
|
||||
|
||||
/* Define to 1 if on MINIX. */
|
||||
#mesondefine _MINIX
|
||||
|
||||
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||
this defined. */
|
||||
#mesondefine _POSIX_1_SOURCE
|
||||
|
||||
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||
#mesondefine _POSIX_SOURCE
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#mesondefine gid_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#mesondefine uid_t
|
||||
|
||||
/* Define to 1 if linux/memfd.h exists */
|
||||
#mesondefine HAVE_LINUX_MEMFD_H
|
||||
|
||||
#mesondefine HAVE_LINUX_INPUT_H
|
||||
|
||||
#mesondefine HAVE_DEV_EVDEV_INPUT_H
|
||||
|
||||
#mesondefine GTK_SYSCONFDIR
|
||||
|
||||
#mesondefine GTK_LOCALEDIR
|
||||
|
||||
#mesondefine GTK_DATADIR
|
||||
|
||||
#mesondefine GTK_LIBDIR
|
||||
|
||||
#mesondefine GTK_PRINT_BACKENDS
|
||||
|
||||
#mesondefine HAVE_CAIRO_SCRIPT_INTERPRETER
|
||||
|
||||
#mesondefine HAVE_HARFBUZZ
|
||||
|
||||
#mesondefine HAVE_PANGOFT
|
||||
|
||||
#mesondefine ISO_CODES_PREFIX
|
||||
|
||||
/* Define if tracker3 is available */
|
||||
#mesondefine HAVE_TRACKER3
|
||||
|
||||
#mesondefine HAVE_F16C
|
||||
|
||||
/* Does the OS support GDesktopAppInfo? */
|
||||
#mesondefine HAVE_DESKTOPAPPINFO
|
@@ -321,6 +321,7 @@
|
||||
<file>paintable_emblem.c</file>
|
||||
<file>paintable_mediastream.c</file>
|
||||
<file>paintable_svg.c</file>
|
||||
<file>paintable_symbolic.c</file>
|
||||
<file>panes.c</file>
|
||||
<file>password_entry.c</file>
|
||||
<file>peg_solitaire.c</file>
|
||||
|
@@ -100,7 +100,11 @@ prepare_drag (GtkDragSource *source,
|
||||
DemoImage *demo = DEMO_IMAGE (widget);
|
||||
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (demo->image));
|
||||
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_PAINTABLE, paintable);
|
||||
/* Textures can be serialized, paintables can't, so special case the textures */
|
||||
if (GDK_IS_TEXTURE (paintable))
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, paintable);
|
||||
else
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_PAINTABLE, paintable);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -129,7 +133,11 @@ copy_image (GtkWidget *widget,
|
||||
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (demo->image));
|
||||
GValue value = G_VALUE_INIT;
|
||||
|
||||
g_value_init (&value, GDK_TYPE_PAINTABLE);
|
||||
/* Textures can be serialized, paintables can't, so special case the textures */
|
||||
if (GDK_IS_TEXTURE (paintable))
|
||||
g_value_init (&value, GDK_TYPE_TEXTURE);
|
||||
else
|
||||
g_value_init (&value, GDK_TYPE_PAINTABLE);
|
||||
g_value_set_object (&value, paintable);
|
||||
gdk_clipboard_set_value (clipboard, &value);
|
||||
g_value_unset (&value);
|
||||
@@ -138,24 +146,46 @@ copy_image (GtkWidget *widget,
|
||||
g_object_unref (paintable);
|
||||
}
|
||||
|
||||
static void
|
||||
paste_image_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GdkClipboard *clipboard = GDK_CLIPBOARD (source);
|
||||
DemoImage *demo = DEMO_IMAGE (data);
|
||||
const GValue *value;
|
||||
|
||||
value = gdk_clipboard_read_value_finish (clipboard, result, NULL);
|
||||
if (value == NULL)
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (demo));
|
||||
g_object_unref (demo);
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_image_set_from_paintable (GTK_IMAGE (demo->image), g_value_get_object (value));
|
||||
g_object_unref (demo);
|
||||
}
|
||||
|
||||
static void
|
||||
paste_image (GtkWidget *widget,
|
||||
const char *action_name,
|
||||
GVariant *parameter)
|
||||
{
|
||||
GdkClipboard *clipboard = gtk_widget_get_clipboard (widget);
|
||||
DemoImage *demo = DEMO_IMAGE (widget);
|
||||
GdkContentProvider *content = gdk_clipboard_get_content (clipboard);
|
||||
GValue value = G_VALUE_INIT;
|
||||
GdkPaintable *paintable;
|
||||
GType type;
|
||||
|
||||
g_value_init (&value, GDK_TYPE_PAINTABLE);
|
||||
if (!gdk_content_provider_get_value (content, &value, NULL))
|
||||
return;
|
||||
if (gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), GDK_TYPE_TEXTURE))
|
||||
type = GDK_TYPE_TEXTURE;
|
||||
else
|
||||
type = GDK_TYPE_PAINTABLE;
|
||||
|
||||
paintable = GDK_PAINTABLE (g_value_get_object (&value));
|
||||
gtk_image_set_from_paintable (GTK_IMAGE (demo->image), paintable);
|
||||
g_value_unset (&value);
|
||||
gdk_clipboard_read_value_async (clipboard,
|
||||
type,
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
paste_image_cb,
|
||||
g_object_ref (widget));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -131,6 +131,19 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
|
||||
gtk_text_buffer_apply_tag (buffer, tag, start, end); \
|
||||
}
|
||||
|
||||
#define VOID_ATTR(attr_name) \
|
||||
{ \
|
||||
tag = gtk_text_tag_table_lookup (table, #attr_name); \
|
||||
if (!tag) \
|
||||
{ \
|
||||
tag = gtk_text_tag_new (#attr_name); \
|
||||
g_object_set (tag, #attr_name, TRUE, NULL); \
|
||||
gtk_text_tag_table_add (table, tag); \
|
||||
g_object_unref (tag); \
|
||||
} \
|
||||
gtk_text_buffer_apply_tag (buffer, tag, start, end); \
|
||||
}
|
||||
|
||||
fg_alpha = bg_alpha = 1.;
|
||||
|
||||
attrs = pango_attr_iterator_get_attrs (iter);
|
||||
@@ -255,6 +268,29 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
|
||||
INT_ATTR (insert_hyphens);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_LINE_HEIGHT:
|
||||
FLOAT_ATTR (line_height);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_ABSOLUTE_LINE_HEIGHT:
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_WORD:
|
||||
VOID_ATTR (word);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_SENTENCE:
|
||||
VOID_ATTR (sentence);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_BASELINE_SHIFT:
|
||||
INT_ATTR (baseline_shift);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_FONT_SCALE:
|
||||
INT_ATTR (font_scale);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_SHAPE:
|
||||
case PANGO_ATTR_ABSOLUTE_SIZE:
|
||||
case PANGO_ATTR_GRAVITY:
|
||||
@@ -263,6 +299,10 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
|
||||
case PANGO_ATTR_BACKGROUND_ALPHA:
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_TEXT_TRANSFORM:
|
||||
INT_ATTR (text_transform);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_INVALID:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
|
@@ -1,6 +1,11 @@
|
||||
/* Pango/Font Rendering
|
||||
*
|
||||
* Demonstrates various aspects of font rendering.
|
||||
* Demonstrates various aspects of font rendering,
|
||||
* such as hinting, antialiasing and grid alignment.
|
||||
*
|
||||
* The demo lets you explore font rendering options
|
||||
* interactively to get a feeling for they affect the
|
||||
* shape and positioning of the glyphs.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
@@ -10,16 +15,21 @@ static GtkWidget *font_button = NULL;
|
||||
static GtkWidget *entry = NULL;
|
||||
static GtkWidget *image = NULL;
|
||||
static GtkWidget *hinting = NULL;
|
||||
static GtkWidget *anti_alias = NULL;
|
||||
static GtkWidget *hint_metrics = NULL;
|
||||
static GtkWidget *up_button = NULL;
|
||||
static GtkWidget *down_button = NULL;
|
||||
static GtkWidget *text_radio = NULL;
|
||||
static GtkWidget *show_grid = NULL;
|
||||
static GtkWidget *show_extents = NULL;
|
||||
static GtkWidget *show_pixels = NULL;
|
||||
static GtkWidget *show_outlines = NULL;
|
||||
|
||||
static PangoContext *context;
|
||||
|
||||
static int scale = 9;
|
||||
static int scale = 7;
|
||||
static double pixel_alpha = 1.0;
|
||||
static double outline_alpha = 0.0;
|
||||
|
||||
static void
|
||||
update_image (void)
|
||||
@@ -27,7 +37,7 @@ update_image (void)
|
||||
const char *text;
|
||||
PangoFontDescription *desc;
|
||||
PangoLayout *layout;
|
||||
PangoRectangle ink, pink, logical;
|
||||
PangoRectangle ink, logical;
|
||||
int baseline;
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
@@ -37,6 +47,8 @@ update_image (void)
|
||||
cairo_font_options_t *fopt;
|
||||
cairo_hint_style_t hintstyle;
|
||||
cairo_hint_metrics_t hintmetrics;
|
||||
cairo_antialias_t antialias;
|
||||
cairo_path_t *path;
|
||||
|
||||
if (!context)
|
||||
context = gtk_widget_create_pango_context (image);
|
||||
@@ -65,6 +77,13 @@ update_image (void)
|
||||
hintmetrics = CAIRO_HINT_METRICS_OFF;
|
||||
cairo_font_options_set_hint_metrics (fopt, hintmetrics);
|
||||
|
||||
if (gtk_check_button_get_active (GTK_CHECK_BUTTON (anti_alias)))
|
||||
antialias = CAIRO_ANTIALIAS_GRAY;
|
||||
else
|
||||
antialias = CAIRO_ANTIALIAS_NONE;
|
||||
cairo_font_options_set_antialias (fopt, antialias);
|
||||
|
||||
pango_context_set_round_glyph_positions (context, hintmetrics == CAIRO_HINT_METRICS_ON);
|
||||
pango_cairo_context_set_font_options (context, fopt);
|
||||
cairo_font_options_destroy (fopt);
|
||||
pango_context_changed (context);
|
||||
@@ -75,7 +94,6 @@ update_image (void)
|
||||
pango_layout_set_font_description (layout, desc);
|
||||
pango_layout_set_text (layout, text, -1);
|
||||
pango_layout_get_extents (layout, &ink, &logical);
|
||||
pink = ink;
|
||||
baseline = pango_layout_get_baseline (layout);
|
||||
|
||||
pango_extents_to_pixels (&ink, NULL);
|
||||
@@ -85,10 +103,14 @@ update_image (void)
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_set_source_rgba (cr, 0, 0, 0, pixel_alpha);
|
||||
|
||||
cairo_move_to (cr, 10, 10);
|
||||
pango_cairo_show_layout (cr, layout);
|
||||
|
||||
pango_cairo_layout_path (cr, layout);
|
||||
path = cairo_copy_path (cr);
|
||||
|
||||
cairo_destroy (cr);
|
||||
g_object_unref (layout);
|
||||
|
||||
@@ -127,7 +149,7 @@ update_image (void)
|
||||
|
||||
if (gtk_check_button_get_active (GTK_CHECK_BUTTON (show_extents)))
|
||||
{
|
||||
cairo_set_source_rgba (cr, 0, 0, 1, 1);
|
||||
cairo_set_source_rgb (cr, 0, 0, 1);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
scale * (10 + pango_units_to_double (logical.x)) - 0.5,
|
||||
@@ -140,17 +162,45 @@ update_image (void)
|
||||
cairo_line_to (cr, scale * (10 + pango_units_to_double (logical.x + logical.width)) + 1,
|
||||
scale * (10 + pango_units_to_double (baseline)) - 0.5);
|
||||
cairo_stroke (cr);
|
||||
cairo_set_source_rgba (cr, 1, 0, 0, 1);
|
||||
cairo_set_source_rgb (cr, 1, 0, 0);
|
||||
cairo_rectangle (cr,
|
||||
scale * (10 + pango_units_to_double (pink.x)) + 0.5,
|
||||
scale * (10 + pango_units_to_double (pink.y)) + 0.5,
|
||||
scale * pango_units_to_double (pink.width) - 1,
|
||||
scale * pango_units_to_double (pink.height) - 1);
|
||||
scale * (10 + ink.x) - 0.5,
|
||||
scale * (10 + ink.y) - 0.5,
|
||||
scale * ink.width + 1,
|
||||
scale * ink.height + 1);
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
for (int i = 0; i < path->num_data; i += path->data[i].header.length)
|
||||
{
|
||||
cairo_path_data_t *data = &path->data[i];
|
||||
switch (data->header.type)
|
||||
{
|
||||
case CAIRO_PATH_CURVE_TO:
|
||||
data[3].point.x *= scale; data[3].point.y *= scale;
|
||||
data[2].point.x *= scale; data[2].point.y *= scale;
|
||||
data[1].point.x *= scale; data[1].point.y *= scale;
|
||||
break;
|
||||
case CAIRO_PATH_LINE_TO:
|
||||
case CAIRO_PATH_MOVE_TO:
|
||||
data[1].point.x *= scale; data[1].point.y *= scale;
|
||||
break;
|
||||
case CAIRO_PATH_CLOSE_PATH:
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
cairo_set_source_rgba (cr, 0, 0, 0, outline_alpha);
|
||||
cairo_move_to (cr, scale * 20 - 0.5, scale * 20 - 0.5);
|
||||
cairo_append_path (cr, path);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
cairo_destroy (cr);
|
||||
|
||||
cairo_path_destroy (path);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -158,10 +208,26 @@ update_image (void)
|
||||
PangoLayoutRun *run;
|
||||
PangoGlyphInfo *g;
|
||||
int i, j;
|
||||
GString *str;
|
||||
gunichar ch;
|
||||
|
||||
if (*text == '\0')
|
||||
text = " ";
|
||||
|
||||
ch = g_utf8_get_char (text);
|
||||
|
||||
str = g_string_new ("");
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
g_string_append_unichar (str, ch);
|
||||
g_string_append_unichar (str, 0x200c);
|
||||
}
|
||||
|
||||
layout = pango_layout_new (context);
|
||||
pango_layout_set_font_description (layout, desc);
|
||||
pango_layout_set_text (layout, "aaaa", -1);
|
||||
pango_layout_set_text (layout, str->str, -1);
|
||||
g_string_free (str, TRUE);
|
||||
pango_layout_get_extents (layout, &ink, &logical);
|
||||
pango_extents_to_pixels (&logical, NULL);
|
||||
|
||||
@@ -176,7 +242,7 @@ update_image (void)
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
g = &(run->glyphs->glyphs[i]);
|
||||
g = &(run->glyphs->glyphs[2*i]);
|
||||
g->geometry.width = PANGO_UNITS_ROUND (g->geometry.width * 3 / 2);
|
||||
}
|
||||
|
||||
@@ -184,7 +250,7 @@ update_image (void)
|
||||
{
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
g = &(run->glyphs->glyphs[i]);
|
||||
g = &(run->glyphs->glyphs[2*i]);
|
||||
g->geometry.x_offset = i * (PANGO_SCALE / 4);
|
||||
g->geometry.y_offset = j * (PANGO_SCALE / 4);
|
||||
}
|
||||
@@ -203,7 +269,6 @@ update_image (void)
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
|
||||
|
||||
gtk_picture_set_pixbuf (GTK_PICTURE (image), pixbuf2);
|
||||
|
||||
g_object_unref (pixbuf2);
|
||||
@@ -211,6 +276,78 @@ update_image (void)
|
||||
pango_font_description_free (desc);
|
||||
}
|
||||
|
||||
static gboolean fading = FALSE;
|
||||
static double start_pixel_alpha;
|
||||
static double end_pixel_alpha;
|
||||
static double start_outline_alpha;
|
||||
static double end_outline_alpha;
|
||||
static gint64 start_time;
|
||||
static gint64 end_time;
|
||||
|
||||
static double
|
||||
ease_out_cubic (double t)
|
||||
{
|
||||
double p = t - 1;
|
||||
return p * p * p + 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
change_alpha (GtkWidget *widget,
|
||||
GdkFrameClock *clock,
|
||||
gpointer user_data)
|
||||
{
|
||||
gint64 now = g_get_monotonic_time ();
|
||||
double t;
|
||||
|
||||
t = ease_out_cubic ((now - start_time) / (double) (end_time - start_time));
|
||||
|
||||
pixel_alpha = start_pixel_alpha + (end_pixel_alpha - start_pixel_alpha) * t;
|
||||
outline_alpha = start_outline_alpha + (end_outline_alpha - start_outline_alpha) * t;
|
||||
|
||||
update_image ();
|
||||
|
||||
if (now >= end_time)
|
||||
{
|
||||
fading = FALSE;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
start_alpha_fade (void)
|
||||
{
|
||||
gboolean pixels;
|
||||
gboolean outlines;
|
||||
|
||||
if (fading)
|
||||
return;
|
||||
|
||||
pixels = gtk_check_button_get_active (GTK_CHECK_BUTTON (show_pixels));
|
||||
outlines = gtk_check_button_get_active (GTK_CHECK_BUTTON (show_outlines));
|
||||
|
||||
start_pixel_alpha = pixel_alpha;
|
||||
if (pixels && outlines)
|
||||
end_pixel_alpha = 0.5;
|
||||
else if (pixels)
|
||||
end_pixel_alpha = 1;
|
||||
else
|
||||
end_pixel_alpha = 0;
|
||||
|
||||
start_outline_alpha = outline_alpha;
|
||||
if (outlines)
|
||||
end_outline_alpha = 1.0;
|
||||
else
|
||||
end_outline_alpha = 0.0;
|
||||
|
||||
start_time = g_get_monotonic_time ();
|
||||
end_time = start_time + G_TIME_SPAN_SECOND / 2;
|
||||
|
||||
fading = TRUE;
|
||||
gtk_widget_add_tick_callback (window, change_alpha, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
update_buttons (void)
|
||||
{
|
||||
@@ -218,20 +355,26 @@ update_buttons (void)
|
||||
gtk_widget_set_sensitive (down_button, scale > 1);
|
||||
}
|
||||
|
||||
static void
|
||||
scale_up (void)
|
||||
static gboolean
|
||||
scale_up (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer user_data)
|
||||
{
|
||||
scale += 1;
|
||||
update_buttons ();
|
||||
update_image ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
scale_down (void)
|
||||
static gboolean
|
||||
scale_down (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer user_data)
|
||||
{
|
||||
scale -= 1;
|
||||
update_buttons ();
|
||||
update_image ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
@@ -252,20 +395,26 @@ do_fontrendering (GtkWidget *do_widget)
|
||||
entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry"));
|
||||
image = GTK_WIDGET (gtk_builder_get_object (builder, "image"));
|
||||
hinting = GTK_WIDGET (gtk_builder_get_object (builder, "hinting"));
|
||||
anti_alias = GTK_WIDGET (gtk_builder_get_object (builder, "antialias"));
|
||||
hint_metrics = GTK_WIDGET (gtk_builder_get_object (builder, "hint_metrics"));
|
||||
text_radio = GTK_WIDGET (gtk_builder_get_object (builder, "text_radio"));
|
||||
show_grid = GTK_WIDGET (gtk_builder_get_object (builder, "show_grid"));
|
||||
show_extents = GTK_WIDGET (gtk_builder_get_object (builder, "show_extents"));
|
||||
show_pixels = GTK_WIDGET (gtk_builder_get_object (builder, "show_pixels"));
|
||||
show_outlines = GTK_WIDGET (gtk_builder_get_object (builder, "show_outlines"));
|
||||
|
||||
g_signal_connect (up_button, "clicked", G_CALLBACK (scale_up), NULL);
|
||||
g_signal_connect (down_button, "clicked", G_CALLBACK (scale_down), NULL);
|
||||
g_signal_connect (entry, "notify::text", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (font_button, "notify::font-desc", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (hinting, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (anti_alias, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (hint_metrics, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (text_radio, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (show_grid, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (show_extents, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (show_pixels, "notify::active", G_CALLBACK (start_alpha_fade), NULL);
|
||||
g_signal_connect (show_outlines, "notify::active", G_CALLBACK (start_alpha_fade), NULL);
|
||||
|
||||
update_image ();
|
||||
|
||||
|
@@ -1,13 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GtkAdjustment" id="scale_adj">
|
||||
<property name="upper">24</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="page-increment">4</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="default-width">1080</property>
|
||||
<property name="default-height">430</property>
|
||||
<property name="default-width">1024</property>
|
||||
<property name="default-height">768</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar">
|
||||
<child type="title">
|
||||
@@ -87,35 +82,62 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Hinting</property>
|
||||
<property name="xalign">1</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
<object class="GtkCheckButton" id="show_pixels">
|
||||
<property name="label">Show _Pixels</property>
|
||||
<property name="use-underline">1</property>
|
||||
<property name="active">1</property>
|
||||
<layout>
|
||||
<property name="column">3</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="hinting">
|
||||
<property name="active">0</property>
|
||||
<property name="valign">center</property>
|
||||
<items>
|
||||
<item translatable="yes" id="none">None</item>
|
||||
<item translatable="yes" id="slight">Slight</item>
|
||||
<item translatable="yes" id="medium">Medium</item>
|
||||
<item translatable="yes" id="full">Full</item>
|
||||
</items>
|
||||
<object class="GtkCheckButton" id="show_outlines">
|
||||
<property name="label">Show _Outline</property>
|
||||
<property name="use-underline">1</property>
|
||||
<layout>
|
||||
<property name="column">3</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">_Hinting</property>
|
||||
<property name="use-underline">1</property>
|
||||
<property name="mnemonic-widget">hinting</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="hinting">
|
||||
<property name="active">0</property>
|
||||
<property name="valign">center</property>
|
||||
<items>
|
||||
<item translatable="yes" id="none">None</item>
|
||||
<item translatable="yes" id="slight">Slight</item>
|
||||
<item translatable="yes" id="medium">Medium</item>
|
||||
<item translatable="yes" id="full">Full</item>
|
||||
</items>
|
||||
</object>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="column">4</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="hint_metrics">
|
||||
<property name="label">Hint Metrics</property>
|
||||
<object class="GtkCheckButton" id="antialias">
|
||||
<property name="label">_Antialias</property>
|
||||
<property name="use-underline">1</property>
|
||||
<property name="active">1</property>
|
||||
<layout>
|
||||
<property name="column">4</property>
|
||||
<property name="row">1</property>
|
||||
@@ -123,21 +145,31 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="show_extents">
|
||||
<property name="label">Show Extents</property>
|
||||
<property name="active">1</property>
|
||||
<object class="GtkCheckButton" id="hint_metrics">
|
||||
<property name="label">Hint _Metrics</property>
|
||||
<property name="use-underline">1</property>
|
||||
<layout>
|
||||
<property name="column">5</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="show_extents">
|
||||
<property name="label">Show _Extents</property>
|
||||
<property name="use-underline">1</property>
|
||||
<layout>
|
||||
<property name="column">6</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="show_grid">
|
||||
<property name="active">1</property>
|
||||
<property name="label">Show Grid</property>
|
||||
<property name="label">Show _Grid</property>
|
||||
<property name="use-underline">1</property>
|
||||
<layout>
|
||||
<property name="column">5</property>
|
||||
<property name="column">6</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
@@ -145,11 +177,24 @@
|
||||
<child>
|
||||
<object class="GtkButton" id="up_button">
|
||||
<property name="icon-name">list-add-symbolic</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<style>
|
||||
<class name="circular"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkShortcutController">
|
||||
<property name="scope">managed</property>
|
||||
<child>
|
||||
<object class="GtkShortcut">
|
||||
<property name="trigger"><Control>plus</property>
|
||||
<property name="action">activate</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="column">6</property>
|
||||
<property name="column">7</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
@@ -157,11 +202,24 @@
|
||||
<child>
|
||||
<object class="GtkButton" id="down_button">
|
||||
<property name="icon-name">list-remove-symbolic</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<style>
|
||||
<class name="circular"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkShortcutController">
|
||||
<property name="scope">managed</property>
|
||||
<child>
|
||||
<object class="GtkShortcut">
|
||||
<property name="trigger"><Control>minus</property>
|
||||
<property name="action">activate</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="column">6</property>
|
||||
<property name="column">7</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
@@ -170,7 +228,7 @@
|
||||
<object class="GtkLabel">
|
||||
<property name="hexpand">1</property>
|
||||
<layout>
|
||||
<property name="column">7</property>
|
||||
<property name="column">8</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
|
@@ -61,12 +61,26 @@ show_page (GtkTextView *text_view,
|
||||
int page)
|
||||
{
|
||||
GtkTextBuffer *buffer;
|
||||
GtkTextIter iter;
|
||||
GtkTextIter iter, start;
|
||||
GtkTextMark *mark;
|
||||
GtkWidget *child;
|
||||
GtkTextChildAnchor *anchor;
|
||||
GtkEventController *controller;
|
||||
GtkTextTag *bold, *mono, *nobreaks;
|
||||
|
||||
buffer = gtk_text_view_get_buffer (text_view);
|
||||
|
||||
bold = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"weight", PANGO_WEIGHT_BOLD,
|
||||
"scale", PANGO_SCALE_X_LARGE,
|
||||
NULL);
|
||||
mono = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"family", "monospace",
|
||||
NULL);
|
||||
nobreaks = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"allow-breaks", FALSE,
|
||||
NULL);
|
||||
|
||||
gtk_text_buffer_set_text (buffer, "", 0);
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
|
||||
gtk_text_buffer_begin_irreversible_action (buffer);
|
||||
@@ -104,17 +118,22 @@ show_page (GtkTextView *text_view,
|
||||
}
|
||||
else if (page == 2)
|
||||
{
|
||||
GtkTextTag *tag;
|
||||
mark = gtk_text_buffer_create_mark (buffer, "mark", &iter, TRUE);
|
||||
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"weight", PANGO_WEIGHT_BOLD,
|
||||
"scale", PANGO_SCALE_X_LARGE,
|
||||
NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "tag", -1, tag, NULL);
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"family", "monospace",
|
||||
NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, " / tag / ", -1, tag, NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "tag", -1, bold, NULL);
|
||||
gtk_text_buffer_insert (buffer, &iter, " /", -1);
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
|
||||
gtk_text_buffer_apply_tag (buffer, nobreaks, &start, &iter);
|
||||
gtk_text_buffer_insert (buffer, &iter, " ", -1);
|
||||
|
||||
gtk_text_buffer_move_mark (buffer, mark, &iter);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "tag", -1, mono, NULL);
|
||||
gtk_text_buffer_insert (buffer, &iter, " /", -1);
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
|
||||
gtk_text_buffer_apply_tag (buffer, nobreaks, &start, &iter);
|
||||
gtk_text_buffer_insert (buffer, &iter, " ", -1);
|
||||
|
||||
anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
|
||||
child = gtk_image_new_from_icon_name ("audio-volume-high-symbolic");
|
||||
@@ -132,20 +151,26 @@ show_page (GtkTextView *text_view,
|
||||
"behavior of mouse and key presses, “lock” a range of text so the "
|
||||
"user can't edit it, or countless other things.\n", -1);
|
||||
insert_link (buffer, &iter, "Go back", 1);
|
||||
|
||||
gtk_text_buffer_delete_mark (buffer, mark);
|
||||
}
|
||||
else if (page == 3)
|
||||
{
|
||||
GtkTextTag *tag;
|
||||
mark = gtk_text_buffer_create_mark (buffer, "mark", &iter, TRUE);
|
||||
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"weight", PANGO_WEIGHT_BOLD,
|
||||
"scale", PANGO_SCALE_X_LARGE,
|
||||
NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "hypertext", -1, tag, NULL);
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"family", "monospace",
|
||||
NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, " / ˈhaɪ pərˌtɛkst / ", -1, tag, NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "hypertext", -1, bold, NULL);
|
||||
gtk_text_buffer_insert (buffer, &iter, " /", -1);
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
|
||||
gtk_text_buffer_apply_tag (buffer, nobreaks, &start, &iter);
|
||||
gtk_text_buffer_insert (buffer, &iter, " ", -1);
|
||||
|
||||
gtk_text_buffer_move_mark (buffer, mark, &iter);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "ˈhaɪ pərˌtɛkst", -1, mono, NULL);
|
||||
gtk_text_buffer_insert (buffer, &iter, " /", -1);
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
|
||||
gtk_text_buffer_apply_tag (buffer, nobreaks, &start, &iter);
|
||||
gtk_text_buffer_insert (buffer, &iter, " ", -1);
|
||||
|
||||
anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
|
||||
child = gtk_image_new_from_icon_name ("audio-volume-high-symbolic");
|
||||
@@ -159,6 +184,8 @@ show_page (GtkTextView *text_view,
|
||||
"Machine-readable text that is not sequential but is organized "
|
||||
"so that related items of information are connected.\n", -1);
|
||||
insert_link (buffer, &iter, "Go back", 1);
|
||||
|
||||
gtk_text_buffer_delete_mark (buffer, mark);
|
||||
}
|
||||
gtk_text_buffer_end_irreversible_action (buffer);
|
||||
}
|
||||
@@ -358,7 +385,7 @@ do_hypertext (GtkWidget *do_widget)
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
GTK_POLICY_NEVER,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
gtk_window_set_child (GTK_WINDOW (window), sw);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), view);
|
||||
|
@@ -8,7 +8,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static GdkPixbuf *avatar_pixbuf_other;
|
||||
static GdkTexture *avatar_texture_other;
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
#define GTK_TYPE_MESSAGE (gtk_message_get_type ())
|
||||
@@ -196,12 +196,9 @@ gtk_message_row_update (GtkMessageRow *row)
|
||||
gtk_button_set_label (GTK_BUTTON (priv->resent_by_button), priv->message->resent_by);
|
||||
|
||||
if (strcmp (priv->message->sender_nick, "@GTKtoolkit") == 0)
|
||||
{
|
||||
gtk_image_set_from_icon_name (priv->avatar_image, "org.gtk.Demo4");
|
||||
gtk_image_set_icon_size (priv->avatar_image, GTK_ICON_SIZE_LARGE);
|
||||
}
|
||||
gtk_image_set_from_icon_name (priv->avatar_image, "org.gtk.Demo4");
|
||||
else
|
||||
gtk_image_set_from_pixbuf (priv->avatar_image, avatar_pixbuf_other);
|
||||
gtk_image_set_from_paintable (priv->avatar_image, GDK_PAINTABLE (avatar_texture_other));
|
||||
|
||||
}
|
||||
|
||||
@@ -344,7 +341,7 @@ do_listbox (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
avatar_pixbuf_other = gdk_pixbuf_new_from_resource_at_scale ("/listbox/apple-red.png", 32, 32, FALSE, NULL);
|
||||
avatar_texture_other = gdk_texture_new_from_resource ("/listbox/apple-red.png");
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
|
@@ -25,6 +25,7 @@
|
||||
<property name="margin-start">8</property>
|
||||
<property name="margin-end">8</property>
|
||||
<property name="icon-name">image-missing</property>
|
||||
<property name="icon-size">large</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">0</property>
|
||||
|
@@ -58,7 +58,7 @@ do_markup (GtkWidget *do_widget)
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 450, 450);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 680);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
stack = gtk_stack_new ();
|
||||
|
@@ -1,5 +1,9 @@
|
||||
|
||||
Text sizes: <span size="xx-small">tiny</span> <span size="x-small">very small</span> <span size="small">small</span> <span size="medium">normal</span> <span size="large">large</span> <span size="x-large">very large</span> <span size="xx-large">huge</span>
|
||||
Text sizes: <span size="xx-small">tiny </span><span size="x-small">very small </span><span size="small">small </span><span size="medium">normal </span><span size="large">large </span><span size="x-large">very large </span><span size="xx-large">huge</span>
|
||||
|
||||
Text styles: <span style="normal">Normal</span> <span style="italic">Italic</span> <span style="oblique">Olique</span>
|
||||
|
||||
Text weights: <span weight="thin">thin</span> <span weight="light">light</span> <span weight="normal">normal</span> <span weight="bold">bold</span> <span weight="ultraheavy">ultraheavy</span>
|
||||
|
||||
Text <span color="gray">c<span color="green">o</span>l<span color="tomato">o</span>rs</span> and <span background="pink">backgrounds</span>
|
||||
|
||||
@@ -15,6 +19,12 @@ OpenType font features: <span font_desc="sans regular" font_features="dlig=0">fe
|
||||
|
||||
Shortcuts: <tt>Monospace</tt> – <b>Bold</b> – <i>Italic</i> – <big>Big</big> – <small>Small</small> – <u>Underlined</u> – <s>Strikethrough</s> – Super<sup>script</sup> – Sub<sub>script</sub>
|
||||
|
||||
<span allow_breaks="false">A</span> hyphenation algorithm is a set of rules, especially one codified for implementation in a computer program, that decides at which points a word can be broken over two lines with a hyphen. For example, a hyphenation algorithm might decide that impeachment can be broken as <span allow_breaks="false">impeach‧ment</span> or <span allow_breaks="false">im‧peachment</span> but not <span allow_breaks="false">impe‧achment.</span>
|
||||
hyphenation algorithm is a <span allow_breaks="false" style="italic">set of rules</span>, especially one codified for implementation in a computer program, that decides at which points a word can be broken over two lines with a hyphen. For example, a hyphenation algorithm might decide that impeachment can be broken as impeach‧ment or im‧peachment but not impe‧achment.
|
||||
|
||||
<span insert_hyphens="false">one/two three/four five/six seven/eight nine/ten</span>
|
||||
|
||||
<span line_height='1.33'>Line height: This is an example of widely spaced text. It was achieved by setting the line-height factor to 1.33. You can set the line-height factor to any value between 0 and 10.
|
||||
Note that the line height affects the spacing between paragraphs as well as between the wrapped lines inside a paragraph.</span>
|
||||
|
||||
Transforms: <span text_transform='uppercase'>straße</span> <span text_transform='capitalize'>up, up and away</span>
|
||||
|
||||
|
@@ -21,8 +21,10 @@ do_menu (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *box;
|
||||
GtkWidget *sw;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *scale;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Menu");
|
||||
@@ -31,11 +33,23 @@ do_menu (GtkWidget *do_widget)
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_window_set_child (GTK_WINDOW (window), sw);
|
||||
gtk_widget_set_vexpand (sw, TRUE);
|
||||
gtk_box_append (GTK_BOX (box), sw);
|
||||
|
||||
widget = demo3_widget_new ("/transparent/portland-rose.jpg");
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), widget);
|
||||
|
||||
scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0.01, 10.0, 0.1);
|
||||
gtk_range_set_value (GTK_RANGE (scale), 1.0);
|
||||
gtk_box_append (GTK_BOX (box), scale);
|
||||
|
||||
g_object_bind_property (gtk_range_get_adjustment (GTK_RANGE (scale)), "value",
|
||||
widget, "scale",
|
||||
G_BINDING_BIDIRECTIONAL);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
@@ -67,6 +67,7 @@ demos = files([
|
||||
'paintable_animated.c',
|
||||
'paintable_emblem.c',
|
||||
'paintable_mediastream.c',
|
||||
'paintable_symbolic.c',
|
||||
'panes.c',
|
||||
'password_entry.c',
|
||||
'peg_solitaire.c',
|
||||
|
@@ -1,8 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>org.gtk.Demo4.desktop</id>
|
||||
<id>org.gtk.Demo4</id>
|
||||
<launchable type="desktop-id">org.gtk.Demo4.desktop</launchable>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>LGPL-2.0+</project_license>
|
||||
<project_license>LGPL-2.1-or-later</project_license>
|
||||
<name>GTK Demo</name>
|
||||
<summary>Program to demonstrate GTK functions</summary>
|
||||
<description>
|
||||
@@ -30,6 +31,7 @@
|
||||
<translation type="gettext">gtk-4.0</translation>
|
||||
<update_contact>matthias.clasen_at_gmail.com</update_contact>
|
||||
<developer_name>Matthias Clasen and others</developer_name>
|
||||
<content_rating type="oars-1.1"/>
|
||||
<releases>
|
||||
<release version="@BUILD_VERSION@" date="@BUILD_DATE@">
|
||||
<description>
|
||||
|
@@ -45,26 +45,27 @@ struct _GtkNuclearIconClass
|
||||
* so that it can be called from all the other demos, too.
|
||||
*/
|
||||
void
|
||||
gtk_nuclear_snapshot (GtkSnapshot *snapshot,
|
||||
double width,
|
||||
double height,
|
||||
double rotation,
|
||||
gboolean draw_background)
|
||||
gtk_nuclear_snapshot (GtkSnapshot *snapshot,
|
||||
const GdkRGBA *foreground,
|
||||
const GdkRGBA *background,
|
||||
double width,
|
||||
double height,
|
||||
double rotation)
|
||||
{
|
||||
#define RADIUS 0.3
|
||||
cairo_t *cr;
|
||||
double size;
|
||||
|
||||
if (draw_background)
|
||||
gtk_snapshot_append_color (snapshot,
|
||||
&(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 },
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
gtk_snapshot_append_color (snapshot,
|
||||
background,
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
|
||||
size = MIN (width, height);
|
||||
cr = gtk_snapshot_append_cairo (snapshot,
|
||||
&GRAPHENE_RECT_INIT ((width - size) / 2.0,
|
||||
(height - size) / 2.0,
|
||||
size, size));
|
||||
gdk_cairo_set_source_rgba (cr, foreground);
|
||||
cairo_translate (cr, width / 2.0, height / 2.0);
|
||||
cairo_scale (cr, size, size);
|
||||
cairo_rotate (cr, rotation);
|
||||
@@ -94,9 +95,10 @@ gtk_nuclear_icon_snapshot (GdkPaintable *paintable,
|
||||
*/
|
||||
|
||||
gtk_nuclear_snapshot (snapshot,
|
||||
&(GdkRGBA) { 0, 0, 0, 1 }, /* black */
|
||||
&(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 }, /* yellow */
|
||||
width, height,
|
||||
nuclear->rotation,
|
||||
TRUE);
|
||||
nuclear->rotation);
|
||||
}
|
||||
|
||||
static GdkPaintableFlags
|
||||
|
@@ -4,10 +4,11 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
void gtk_nuclear_snapshot (GtkSnapshot *snapshot,
|
||||
const GdkRGBA *foreground,
|
||||
const GdkRGBA *background,
|
||||
double width,
|
||||
double height,
|
||||
double rotation,
|
||||
gboolean draw_background);
|
||||
double rotation);
|
||||
|
||||
GdkPaintable * gtk_nuclear_icon_new (double rotation);
|
||||
GdkPaintable * gtk_nuclear_animation_new (gboolean draw_background);
|
||||
|
@@ -65,9 +65,12 @@ gtk_nuclear_animation_snapshot (GdkPaintable *paintable,
|
||||
|
||||
/* We call the function from the previous example here. */
|
||||
gtk_nuclear_snapshot (snapshot,
|
||||
&(GdkRGBA) { 0, 0, 0, 1 }, /* black */
|
||||
nuclear->draw_background
|
||||
? &(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 } /* yellow */
|
||||
: &(GdkRGBA) { 0, 0, 0, 0 }, /* transparent */
|
||||
width, height,
|
||||
2 * G_PI * nuclear->progress / MAX_PROGRESS,
|
||||
nuclear->draw_background);
|
||||
2 * G_PI * nuclear->progress / MAX_PROGRESS);
|
||||
}
|
||||
|
||||
static GdkPaintable *
|
||||
|
@@ -73,9 +73,10 @@ gtk_nuclear_media_stream_snapshot (GdkPaintable *paintable,
|
||||
|
||||
/* We call the function from the previous example here. */
|
||||
gtk_nuclear_snapshot (snapshot,
|
||||
&(GdkRGBA) { 0, 0, 0, 1 }, /* black */
|
||||
&(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 }, /* yellow */
|
||||
width, height,
|
||||
2 * G_PI * nuclear->progress / DURATION,
|
||||
TRUE);
|
||||
2 * G_PI * nuclear->progress / DURATION);
|
||||
}
|
||||
|
||||
static GdkPaintable *
|
||||
|
208
demos/gtk-demo/paintable_symbolic.c
Normal file
208
demos/gtk-demo/paintable_symbolic.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/* Paintable/Symbolic Paintable
|
||||
*
|
||||
* GdkPaintables can be made to follow the theme's colors. GTK calls
|
||||
* icons that do this symbolic icons, paintables that want to have
|
||||
* the same effect can implement the GtkSymbolicPaintable interface.
|
||||
*
|
||||
* We will adapt the original paintable example by adding the ability
|
||||
* to recolor the paintable based on the symbolic colors.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "paintable.h"
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
/* First, add the boilerplate for the object itself.
|
||||
* This part would normally go in the header.
|
||||
*/
|
||||
#define GTK_TYPE_NUCLEAR_SYMBOLIC (gtk_nuclear_symbolic_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkNuclearSymbolic, gtk_nuclear_symbolic, GTK, NUCLEAR_SYMBOLIC, GObject)
|
||||
|
||||
/* Declare a few warning levels, so we can pick colors based on them */
|
||||
typedef enum
|
||||
{
|
||||
WARNING_NONE,
|
||||
WARNING_ALERT,
|
||||
WARNING_EMERGENCY
|
||||
} WarningLevel;
|
||||
|
||||
/* Declare the struct. */
|
||||
struct _GtkNuclearSymbolic
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
WarningLevel warning_level;
|
||||
};
|
||||
|
||||
struct _GtkNuclearSymbolicClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/* Add a function to draw the nuclear icon in the given colors */
|
||||
static void
|
||||
gtk_nuclear_symbolic_snapshot_symbolic (GtkSymbolicPaintable *paintable,
|
||||
GdkSnapshot *snapshot,
|
||||
double width,
|
||||
double height,
|
||||
const GdkRGBA *colors,
|
||||
gsize n_colors)
|
||||
{
|
||||
GtkNuclearSymbolic *self = GTK_NUCLEAR_SYMBOLIC (paintable);
|
||||
static const GdkRGBA transparent = { 0, };
|
||||
const GdkRGBA *bg_color;
|
||||
|
||||
/* select the right background color from the warning level */
|
||||
switch (self->warning_level)
|
||||
{
|
||||
case WARNING_NONE:
|
||||
bg_color = &transparent;
|
||||
break;
|
||||
case WARNING_ALERT:
|
||||
bg_color = &colors[GTK_SYMBOLIC_COLOR_WARNING];
|
||||
break;
|
||||
case WARNING_EMERGENCY:
|
||||
bg_color = &colors[GTK_SYMBOLIC_COLOR_ERROR];
|
||||
break;
|
||||
default:
|
||||
/* This should never happen, but we better do defensive coding
|
||||
* with this critical icon */
|
||||
g_assert_not_reached ();
|
||||
bg_color = &transparent;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Draw the icon with the selected warning color */
|
||||
gtk_nuclear_snapshot (snapshot,
|
||||
&colors[GTK_SYMBOLIC_COLOR_FOREGROUND],
|
||||
bg_color,
|
||||
width, height,
|
||||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_nuclear_symbolic_symbolic_paintable_init (GtkSymbolicPaintableInterface *iface)
|
||||
{
|
||||
iface->snapshot_symbolic = gtk_nuclear_symbolic_snapshot_symbolic;
|
||||
}
|
||||
|
||||
/* We need to implement the functionality required by the GdkPaintable interface */
|
||||
static void
|
||||
gtk_nuclear_symbolic_snapshot (GdkPaintable *paintable,
|
||||
GdkSnapshot *snapshot,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
/* Calling this function without passing a color is a neat trick
|
||||
* to make GTK use default colors and otherwise forward the call
|
||||
* to the snapshotting function above.
|
||||
*/
|
||||
gtk_symbolic_paintable_snapshot_symbolic (GTK_SYMBOLIC_PAINTABLE (paintable),
|
||||
snapshot,
|
||||
width, height,
|
||||
NULL, 0);
|
||||
}
|
||||
|
||||
static GdkPaintableFlags
|
||||
gtk_nuclear_symbolic_get_flags (GdkPaintable *paintable)
|
||||
{
|
||||
/* This image has a static size, but the contents may change:
|
||||
* We draw different things when the warning level changes.
|
||||
*/
|
||||
return GDK_PAINTABLE_STATIC_SIZE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_nuclear_symbolic_paintable_init (GdkPaintableInterface *iface)
|
||||
{
|
||||
iface->snapshot = gtk_nuclear_symbolic_snapshot;
|
||||
iface->get_flags = gtk_nuclear_symbolic_get_flags;
|
||||
}
|
||||
|
||||
/* When defining the GType, we need to implement bot the GdkPaintable
|
||||
* and the GtkSymbolicPaintable interface */
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkNuclearSymbolic, gtk_nuclear_symbolic, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
||||
gtk_nuclear_symbolic_paintable_init)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_SYMBOLIC_PAINTABLE,
|
||||
gtk_nuclear_symbolic_symbolic_paintable_init))
|
||||
|
||||
static void
|
||||
gtk_nuclear_symbolic_class_init (GtkNuclearSymbolicClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_nuclear_symbolic_init (GtkNuclearSymbolic *nuclear)
|
||||
{
|
||||
}
|
||||
|
||||
/* And finally, we add the simple constructor we declared in the header. */
|
||||
GdkPaintable *
|
||||
gtk_nuclear_symbolic_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_NUCLEAR_SYMBOLIC, NULL);
|
||||
}
|
||||
|
||||
/* Add some fun feature to the button */
|
||||
static void
|
||||
nuclear_button_clicked (GtkButton *button,
|
||||
GtkNuclearSymbolic *nuclear)
|
||||
{
|
||||
if (nuclear->warning_level >= WARNING_EMERGENCY)
|
||||
{
|
||||
/* On maximum warning level, reset the warning */
|
||||
nuclear->warning_level = WARNING_NONE;
|
||||
/* And sometimes (but not always to confuse people)
|
||||
* close the window.
|
||||
*/
|
||||
if (g_random_boolean ())
|
||||
gtk_window_close (GTK_WINDOW (window));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise just increase the warning level */
|
||||
nuclear->warning_level++;
|
||||
}
|
||||
|
||||
/* Don't forget to emit the signal causing the paintable to redraw.
|
||||
* Changing the warning level changes the background color after all.
|
||||
*/
|
||||
gdk_paintable_invalidate_contents (GDK_PAINTABLE (nuclear));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_paintable_symbolic (GtkWidget *do_widget)
|
||||
{
|
||||
GdkPaintable *nuclear;
|
||||
GtkWidget *image, *button;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Don't click!");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
button = gtk_button_new ();
|
||||
gtk_window_set_child (GTK_WINDOW (window), button);
|
||||
|
||||
nuclear = gtk_nuclear_symbolic_new ();
|
||||
image = gtk_image_new_from_paintable (nuclear);
|
||||
|
||||
gtk_button_set_child (GTK_BUTTON (button), image);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (nuclear_button_clicked), nuclear);
|
||||
g_object_unref (nuclear);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
return window;
|
||||
}
|
@@ -1,8 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>org.gtk.IconBrowser4.desktop</id>
|
||||
<id>org.gtk.IconBrowser4</id>
|
||||
<launchable type="desktop-id">org.gtk.IconBrowser4.desktop</launchable>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>LGPL-2.0+</project_license>
|
||||
<project_license>LGPL-2.1-or-later</project_license>
|
||||
<name>GTK Icon Browser</name>
|
||||
<summary>Program to browse themed icons</summary>
|
||||
<description>
|
||||
@@ -29,6 +30,7 @@
|
||||
<translation type="gettext">gtk-4.0</translation>
|
||||
<update_contact>matthias.clasen_at_gmail.com</update_contact>
|
||||
<developer_name>Matthias Clasen and others</developer_name>
|
||||
<content_rating type="oars-1.1"/>
|
||||
<releases>
|
||||
<release version="@BUILD_VERSION@" date="@BUILD_DATE@">
|
||||
<description>
|
||||
|
@@ -24,7 +24,6 @@
|
||||
#include "gtkrendererpaintableprivate.h"
|
||||
|
||||
#include "gsk/gskrendernodeparserprivate.h"
|
||||
#include "gsk/gl/gskglrenderer.h"
|
||||
#include "gsk/ngl/gsknglrenderer.h"
|
||||
#ifdef GDK_WINDOWING_BROADWAY
|
||||
#include "gsk/broadway/gskbroadwayrenderer.h"
|
||||
@@ -61,7 +60,7 @@ struct _NodeEditorWindow
|
||||
|
||||
GtkWidget *renderer_listbox;
|
||||
GListStore *renderers;
|
||||
GdkPaintable *paintable;
|
||||
GskRenderNode *node;
|
||||
|
||||
GFileMonitor *file_monitor;
|
||||
|
||||
@@ -168,7 +167,6 @@ static void
|
||||
text_changed (GtkTextBuffer *buffer,
|
||||
NodeEditorWindow *self)
|
||||
{
|
||||
GskRenderNode *node;
|
||||
char *text;
|
||||
GBytes *bytes;
|
||||
GtkTextIter iter;
|
||||
@@ -179,10 +177,12 @@ text_changed (GtkTextBuffer *buffer,
|
||||
text_buffer_remove_all_tags (self->text_buffer);
|
||||
bytes = g_bytes_new_take (text, strlen (text));
|
||||
|
||||
g_clear_pointer (&self->node, gsk_render_node_unref);
|
||||
|
||||
/* If this is too slow, go fix the parser performance */
|
||||
node = gsk_render_node_deserialize (bytes, deserialize_error_func, self);
|
||||
self->node = gsk_render_node_deserialize (bytes, deserialize_error_func, self);
|
||||
g_bytes_unref (bytes);
|
||||
if (node)
|
||||
if (self->node)
|
||||
{
|
||||
/* XXX: Is this code necessary or can we have API to turn nodes into paintables? */
|
||||
GtkSnapshot *snapshot;
|
||||
@@ -191,10 +191,9 @@ text_changed (GtkTextBuffer *buffer,
|
||||
guint i;
|
||||
|
||||
snapshot = gtk_snapshot_new ();
|
||||
gsk_render_node_get_bounds (node, &bounds);
|
||||
gsk_render_node_get_bounds (self->node, &bounds);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- bounds.origin.x, - bounds.origin.y));
|
||||
gtk_snapshot_append_node (snapshot, node);
|
||||
gsk_render_node_unref (node);
|
||||
gtk_snapshot_append_node (snapshot, self->node);
|
||||
paintable = gtk_snapshot_free_to_paintable (snapshot, &bounds.size);
|
||||
gtk_picture_set_paintable (GTK_PICTURE (self->picture), paintable);
|
||||
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (self->renderers)); i++)
|
||||
@@ -338,15 +337,9 @@ text_view_query_tooltip_cb (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
load_file_contents (NodeEditorWindow *self,
|
||||
GFile *file)
|
||||
load_bytes (NodeEditorWindow *self,
|
||||
GBytes *bytes)
|
||||
{
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = g_file_load_bytes (file, NULL, NULL, NULL);
|
||||
if (bytes == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!g_utf8_validate (g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), NULL))
|
||||
{
|
||||
g_bytes_unref (bytes);
|
||||
@@ -362,6 +355,105 @@ load_file_contents (NodeEditorWindow *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
load_file_contents (NodeEditorWindow *self,
|
||||
GFile *file)
|
||||
{
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = g_file_load_bytes (file, NULL, NULL, NULL);
|
||||
if (bytes == NULL)
|
||||
return FALSE;
|
||||
|
||||
return load_bytes (self, bytes);
|
||||
}
|
||||
|
||||
static GdkContentProvider *
|
||||
on_picture_drag_prepare_cb (GtkDragSource *source,
|
||||
double x,
|
||||
double y,
|
||||
NodeEditorWindow *self)
|
||||
{
|
||||
if (self->node == NULL)
|
||||
return NULL;
|
||||
|
||||
return gdk_content_provider_new_typed (GSK_TYPE_RENDER_NODE, self->node);
|
||||
}
|
||||
|
||||
static void
|
||||
on_picture_drop_read_done_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
NodeEditorWindow *self = data;
|
||||
GOutputStream *stream = G_OUTPUT_STREAM (source);
|
||||
GdkDrop *drop = g_object_get_data (source, "drop");
|
||||
GdkDragAction action = 0;
|
||||
GBytes *bytes;
|
||||
|
||||
if (g_output_stream_splice_finish (stream, res, NULL) >= 0)
|
||||
{
|
||||
bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (stream));
|
||||
if (load_bytes (self, bytes))
|
||||
action = GDK_ACTION_COPY;
|
||||
}
|
||||
|
||||
g_object_unref (self);
|
||||
gdk_drop_finish (drop, action);
|
||||
g_object_unref (drop);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
on_picture_drop_read_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
NodeEditorWindow *self = data;
|
||||
GdkDrop *drop = GDK_DROP (source);
|
||||
GInputStream *input;
|
||||
GOutputStream *output;
|
||||
|
||||
input = gdk_drop_read_finish (drop, res, NULL, NULL);
|
||||
if (input == NULL)
|
||||
{
|
||||
g_object_unref (self);
|
||||
gdk_drop_finish (drop, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
output = g_memory_output_stream_new_resizable ();
|
||||
g_object_set_data (G_OBJECT (output), "drop", drop);
|
||||
g_object_ref (drop);
|
||||
|
||||
g_output_stream_splice_async (output,
|
||||
input,
|
||||
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
on_picture_drop_read_done_cb,
|
||||
self);
|
||||
g_object_unref (output);
|
||||
g_object_unref (input);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_picture_drop_cb (GtkDropTargetAsync *dest,
|
||||
GdkDrop *drop,
|
||||
double x,
|
||||
double y,
|
||||
NodeEditorWindow *self)
|
||||
{
|
||||
gdk_drop_read_async (drop,
|
||||
(const char *[2]) { "application/x-gtk-render-node", NULL },
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
on_picture_drop_read_cb,
|
||||
g_object_ref (self));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
file_changed_cb (GFileMonitor *monitor,
|
||||
GFile *file,
|
||||
@@ -736,6 +828,7 @@ node_editor_window_finalize (GObject *object)
|
||||
|
||||
g_array_free (self->errors, TRUE);
|
||||
|
||||
g_clear_pointer (&self->node, gsk_render_node_unref);
|
||||
g_clear_object (&self->renderers);
|
||||
|
||||
G_OBJECT_CLASS (node_editor_window_parent_class)->finalize (object);
|
||||
@@ -778,12 +871,9 @@ node_editor_window_realize (GtkWidget *widget)
|
||||
NULL,
|
||||
"Default");
|
||||
#endif
|
||||
node_editor_window_add_renderer (self,
|
||||
gsk_gl_renderer_new (),
|
||||
"OpenGL");
|
||||
node_editor_window_add_renderer (self,
|
||||
gsk_ngl_renderer_new (),
|
||||
"NGL");
|
||||
"OpenGL");
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
node_editor_window_add_renderer (self,
|
||||
gsk_vulkan_renderer_new (),
|
||||
@@ -848,6 +938,8 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
|
||||
gtk_widget_class_bind_template_callback (widget_class, testcase_save_clicked_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, testcase_name_entry_changed_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, dark_mode_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_picture_drag_prepare_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_picture_drop_cb);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
|
@@ -198,8 +198,22 @@
|
||||
<child>
|
||||
<object class="GtkPicture" id="picture">
|
||||
<property name="can-shrink">0</property>
|
||||
<property name="keep-aspect-ratio">1</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<property name="actions">copy</property>
|
||||
<signal name="prepare" handler="on_picture_drag_prepare_cb" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropTargetAsync">
|
||||
<property name="actions">copy</property>
|
||||
<property name="formats">application/x-gtk-render-node</property>
|
||||
<signal name="drop" handler="on_picture_drop_cb" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@@ -1,8 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>org.gtk.PrintEditor4.desktop</id>
|
||||
<id>org.gtk.PrintEditor4</id>
|
||||
<launchable type="desktop-id">org.gtk.PrintEditor4.desktop</launchable>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>LGPL-2.0+</project_license>
|
||||
<project_license>LGPL-2.1-or-later</project_license>
|
||||
<name>GTK Print Editor</name>
|
||||
<summary>Program to demonstrate GTK printing</summary>
|
||||
<description>
|
||||
@@ -24,6 +25,7 @@
|
||||
<translation type="gettext">gtk-4.0</translation>
|
||||
<update_contact>matthias.clasen_at_gmail.com</update_contact>
|
||||
<developer_name>Matthias Clasen and others</developer_name>
|
||||
<content_rating type="oars-1.1"/>
|
||||
<releases>
|
||||
<release version="3.99.0" date="2020-07-30">
|
||||
<description>
|
||||
|
BIN
demos/widget-factory/beach.jpg
Normal file
BIN
demos/widget-factory/beach.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 94 KiB |
BIN
demos/widget-factory/nyc.jpg
Normal file
BIN
demos/widget-factory/nyc.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
@@ -1,8 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>org.gtk.WidgetFactory4.desktop</id>
|
||||
<id>org.gtk.WidgetFactory4</id>
|
||||
<launchable type="desktop-id">org.gtk.WidgetFactory4.desktop</launchable>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>LGPL-2.0+</project_license>
|
||||
<project_license>LGPL-2.1-or-later</project_license>
|
||||
<name>GTK Widget Factory</name>
|
||||
<summary>Program to demonstrate GTK functions</summary>
|
||||
<description>
|
||||
@@ -31,6 +32,7 @@
|
||||
<translation type="gettext">gtk-4.0</translation>
|
||||
<update_contact>matthias.clasen_at_gmail.com</update_contact>
|
||||
<developer_name>Matthias Clasen and others</developer_name>
|
||||
<content_rating type="oars-1.1"/>
|
||||
<releases>
|
||||
<release version="@BUILD_VERSION@" date="@BUILD_DATE@">
|
||||
<description>
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.9 MiB |
Binary file not shown.
Before Width: | Height: | Size: 2.0 MiB After Width: | Height: | Size: 59 KiB |
@@ -696,6 +696,37 @@ on_range_to_changed (GtkSpinButton *to)
|
||||
gtk_spin_button_set_value (from, v2);
|
||||
}
|
||||
|
||||
static GdkContentProvider *
|
||||
on_picture_drag_prepare (GtkDragSource *source,
|
||||
double x,
|
||||
double y,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkWidget *picture;
|
||||
|
||||
picture = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
|
||||
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, gtk_picture_get_paintable (GTK_PICTURE (picture)));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_picture_drop (GtkDropTarget *dest,
|
||||
const GValue *value,
|
||||
double x,
|
||||
double y,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkWidget *picture;
|
||||
GdkPaintable *paintable;
|
||||
|
||||
picture = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
|
||||
paintable = g_value_get_object (value);
|
||||
|
||||
gtk_picture_set_paintable (GTK_PICTURE (picture), paintable);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
info_bar_response (GtkWidget *infobar, int response_id)
|
||||
{
|
||||
@@ -1182,7 +1213,7 @@ populate_flowbox (GtkWidget *flowbox)
|
||||
GtkWidget *child;
|
||||
int i;
|
||||
const char *resources[] = {
|
||||
"sunset.jpg", "snowy.jpg", "portland-rose.jpg"
|
||||
"sunset.jpg", "portland-rose.jpg", "beach.jpg", "nyc.jpg"
|
||||
};
|
||||
|
||||
if (GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (flowbox), "populated")))
|
||||
@@ -2040,6 +2071,8 @@ activate (GApplication *app)
|
||||
"on_page_combo_changed", (GCallback)on_page_combo_changed,
|
||||
"on_range_from_changed", (GCallback)on_range_from_changed,
|
||||
"on_range_to_changed", (GCallback)on_range_to_changed,
|
||||
"on_picture_drag_prepare", (GCallback)on_picture_drag_prepare,
|
||||
"on_picture_drop", (GCallback)on_picture_drop,
|
||||
"tab_close_cb", (GCallback)tab_close_cb,
|
||||
"increase_icon_size", (GCallback)increase_icon_size,
|
||||
"decrease_icon_size", (GCallback)decrease_icon_size,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/org/gtk/WidgetFactory4">
|
||||
<file preprocess="xml-stripblanks">widget-factory.ui</file>
|
||||
<file alias='widget-factory.ui'>widget-factory.uic</file>
|
||||
</gresource>
|
||||
<gresource prefix="/org/gtk/WidgetFactory4">
|
||||
<file>widget-factory.css</file>
|
||||
@@ -115,7 +115,8 @@
|
||||
<gresource prefix="/org/gtk/WidgetFactory4">
|
||||
<file>gtk-logo.webm</file>
|
||||
<file>sunset.jpg</file>
|
||||
<file>snowy.jpg</file>
|
||||
<file>portland-rose.jpg</file>
|
||||
<file>nyc.jpg</file>
|
||||
<file>beach.jpg</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
@@ -1051,22 +1051,9 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<property name="spacing">10</property>
|
||||
<property name="hexpand">1</property>
|
||||
<child>
|
||||
<object class="GtkFrame" id="frame1">
|
||||
<property name="valign">start</property>
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="label" translatable="yes"><b>Video</b></property>
|
||||
<property name="use-markup">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<object class="GtkFrame">
|
||||
<child>
|
||||
<object class="GtkVideo">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin-start">6</property>
|
||||
<property name="margin-end">6</property>
|
||||
<property name="margin-top">6</property>
|
||||
<property name="margin-bottom">6</property>
|
||||
<property name="autoplay">1</property>
|
||||
<property name="loop">1</property>
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/gtk-logo.webm</property>
|
||||
@@ -1075,66 +1062,78 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="vexpand">1</property>
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<object class="GtkFrame">
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="label" translatable="yes"><b>Text Styles</b></property>
|
||||
<property name="use-markup">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">10</property>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="vexpand">1</property>
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<property name="propagate-natural-height">1</property>
|
||||
<property name="propagate-natural-width">1</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Large Title</property>
|
||||
<style><class name="large-title"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 1</property>
|
||||
<style><class name="title-1"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 2</property>
|
||||
<style><class name="title-2"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 3</property>
|
||||
<style><class name="title-3"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 4</property>
|
||||
<style><class name="title-4"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Heading</property>
|
||||
<style><class name="heading"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Body</property>
|
||||
<style><class name="body"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Caption Heading</property>
|
||||
<style><class name="caption-heading"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Caption</property>
|
||||
<style><class name="caption"/></style>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Large Title</property>
|
||||
<style><class name="large-title"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 1</property>
|
||||
<style><class name="title-1"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 2</property>
|
||||
<style><class name="title-2"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 3</property>
|
||||
<style><class name="title-3"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 4</property>
|
||||
<style><class name="title-4"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Heading</property>
|
||||
<style><class name="heading"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Body</property>
|
||||
<style><class name="body"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Caption Heading</property>
|
||||
<style><class name="caption-heading"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Caption</property>
|
||||
<style><class name="caption"/></style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@@ -1251,8 +1250,21 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="child">
|
||||
<object class="GtkBox" id="box6">
|
||||
<property name="orientation">vertical</property>
|
||||
<object class="GtkPicture">
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/sunset.jpg</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<property name="actions">copy</property>
|
||||
<signal name="prepare" handler="on_picture_drag_prepare" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropTarget">
|
||||
<property name="actions">copy</property>
|
||||
<property name="formats">GdkTexture</property>
|
||||
<signal name="drop" handler="on_picture_drop" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="tab">
|
||||
@@ -1265,8 +1277,21 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="child">
|
||||
<object class="GtkBox" id="box7">
|
||||
<property name="orientation">vertical</property>
|
||||
<object class="GtkPicture">
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/nyc.jpg</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<property name="actions">copy</property>
|
||||
<signal name="prepare" handler="on_picture_drag_prepare" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropTarget">
|
||||
<property name="actions">copy</property>
|
||||
<property name="formats">GdkTexture</property>
|
||||
<signal name="drop" handler="on_picture_drop" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="tab">
|
||||
@@ -1278,10 +1303,22 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="position">2</property>
|
||||
<property name="child">
|
||||
<object class="GtkBox" id="box8">
|
||||
<property name="orientation">vertical</property>
|
||||
<object class="GtkPicture">
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/beach.jpg</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<property name="actions">copy</property>
|
||||
<signal name="prepare" handler="on_picture_drag_prepare" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropTarget">
|
||||
<property name="actions">copy</property>
|
||||
<property name="formats">GdkTexture</property>
|
||||
<signal name="drop" handler="on_picture_drop" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="tab">
|
||||
@@ -1299,7 +1336,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="child">
|
||||
<object class="GtkBox" id="box9">
|
||||
<object class="GtkBox" id="box8">
|
||||
<property name="orientation">vertical</property>
|
||||
</object>
|
||||
</property>
|
||||
|
BIN
demos/widget-factory/widget-factory.uic
Normal file
BIN
demos/widget-factory/widget-factory.uic
Normal file
Binary file not shown.
@@ -13,7 +13,7 @@ devhelp = true
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable"
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
|
||||
[theme]
|
||||
name = "basic"
|
||||
|
@@ -13,7 +13,7 @@ devhelp = true
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable"
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
|
||||
[theme]
|
||||
name = "basic"
|
||||
|
@@ -14,7 +14,7 @@ search_index = true
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable"
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
|
||||
[dependencies."cairo-1.0"]
|
||||
name = "Cairo"
|
||||
|
@@ -1,11 +1,15 @@
|
||||
expand_content_md_files = [
|
||||
]
|
||||
|
||||
gdk4_toml = configure_file(input: 'gdk4.toml.in', output: 'gdk4.toml', configuration: toml_conf)
|
||||
gdk4x11_toml = configure_file(input: 'gdk4-x11.toml.in', output: 'gdk4-x11.toml', configuration: toml_conf)
|
||||
gdk4wayland_toml = configure_file(input: 'gdk4-wayland.toml.in', output: 'gdk4-wayland.toml', configuration: toml_conf)
|
||||
|
||||
if get_option('gtk_doc')
|
||||
gdk4_toml = configure_file(
|
||||
input: 'gdk4.toml.in',
|
||||
output: 'gdk4.toml',
|
||||
configuration: toml_conf,
|
||||
install: true,
|
||||
install_dir: docs_dir / 'gdk4',
|
||||
)
|
||||
|
||||
custom_target('gdk4-doc',
|
||||
input: [ gdk4_toml, gdk_gir[0] ],
|
||||
output: 'gdk4',
|
||||
@@ -28,6 +32,14 @@ if get_option('gtk_doc')
|
||||
)
|
||||
|
||||
if x11_enabled
|
||||
gdk4x11_toml = configure_file(
|
||||
input: 'gdk4-x11.toml.in',
|
||||
output: 'gdk4-x11.toml',
|
||||
configuration: toml_conf,
|
||||
install: true,
|
||||
install_dir: docs_dir / 'gdk4-x11',
|
||||
)
|
||||
|
||||
custom_target('gdk4-x11-doc',
|
||||
input: [ gdk4x11_toml, gdk_x11_gir[0] ],
|
||||
output: 'gdk4-x11',
|
||||
@@ -52,6 +64,14 @@ if get_option('gtk_doc')
|
||||
endif
|
||||
|
||||
if wayland_enabled
|
||||
gdk4wayland_toml = configure_file(
|
||||
input: 'gdk4-wayland.toml.in',
|
||||
output: 'gdk4-wayland.toml',
|
||||
configuration: toml_conf,
|
||||
install: true,
|
||||
install_dir: docs_dir / 'gdk4-wayland',
|
||||
)
|
||||
|
||||
custom_target('gdk4-wayland-doc',
|
||||
input: [ gdk4wayland_toml, gdk_wayland_gir[0] ],
|
||||
output: 'gdk4-wayland',
|
||||
|
@@ -3,11 +3,14 @@
|
||||
|
||||
// A map between namespaces and base URLs for their online documentation
|
||||
baseURLs = [
|
||||
[ 'Gdk', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://gnome.pages.gitlab.gnome.org/gtk/gsk4/' ],
|
||||
[ 'Gtk', 'https://gnome.pages.gitlab.gnome.org/gtk/gtk4/' ],
|
||||
[ 'Pango', 'https://gnome.pages/gitlab.gnome.org/pango/pango/' ],
|
||||
[ 'PangoCairo', 'https://gnome.pages.gitlab.gnome.org/pango/pangocairo/' ],
|
||||
[ 'GLib', 'https://docs.gtk.org/glib/' ],
|
||||
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
|
||||
[ 'Gio', 'https://docs.gtk.org/gio/' ],
|
||||
[ 'Gdk', 'https://docs.gtk.org/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://docs.gtk.org/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://docs.gtk.org/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://docs.gtk.org/gsk4/' ],
|
||||
[ 'Gtk', 'https://docs.gtk.org/gtk4/' ],
|
||||
[ 'Pango', 'https://docs.gtk.org/Pango/' ],
|
||||
[ 'PangoCairo', 'https://docs.gtk.org/PangoCairo/' ],
|
||||
]
|
||||
|
@@ -14,7 +14,7 @@ search_index = true
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable/"
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
|
||||
[dependencies."Graphene-1.0"]
|
||||
name = "Graphene"
|
||||
|
@@ -1,6 +1,12 @@
|
||||
gsk4_toml = configure_file(input: 'gsk4.toml.in', output: 'gsk4.toml', configuration: toml_conf)
|
||||
|
||||
if get_option('gtk_doc')
|
||||
gsk4_toml = configure_file(
|
||||
input: 'gsk4.toml.in',
|
||||
output: 'gsk4.toml',
|
||||
configuration: toml_conf,
|
||||
install: true,
|
||||
install_dir: docs_dir / 'gsk4',
|
||||
)
|
||||
|
||||
custom_target('gsk4-doc',
|
||||
input: [ gsk4_toml, gsk_gir[0] ],
|
||||
output: 'gsk4',
|
||||
|
@@ -3,11 +3,14 @@
|
||||
|
||||
// A map between namespaces and base URLs for their online documentation
|
||||
baseURLs = [
|
||||
[ 'Gdk', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://gnome.pages.gitlab.gnome.org/gtk/gsk4/' ],
|
||||
[ 'Gtk', 'https://gnome.pages.gitlab.gnome.org/gtk/gtk4/' ],
|
||||
[ 'Pango', 'https://gnome.pages/gitlab.gnome.org/pango/pango/' ],
|
||||
[ 'PangoCairo', 'https://gnome.pages.gitlab.gnome.org/pango/pangocairo/' ],
|
||||
[ 'GLib', 'https://docs.gtk.org/glib/' ],
|
||||
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
|
||||
[ 'Gio', 'https://docs.gtk.org/gio/' ],
|
||||
[ 'Gdk', 'https://docs.gtk.org/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://docs.gtk.org/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://docs.gtk.org/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://docs.gtk.org/gsk4/' ],
|
||||
[ 'Gtk', 'https://docs.gtk.org/gtk4/' ],
|
||||
[ 'Pango', 'https://docs.gtk.org/Pango/' ],
|
||||
[ 'PangoCairo', 'https://docs.gtk.org/PangoCairo/' ],
|
||||
]
|
||||
|
@@ -162,6 +162,8 @@ done with
|
||||
|caret-color|[CSS Basic User Interface Level 3](https://www.w3.org/TR/css3-ui/#caret-color) | CSS allows an auto value |
|
||||
|-gtk-secondary-caret-color|[Color](https://www.w3.org/TR/css-color-3/#valuea-def-color) | used for the secondary caret in bidirectional text |
|
||||
|letter-spacing| [CSS Text Level 3](https://www.w3.org/TR/css3-text/#letter-spacing) | |
|
||||
|text-transform| [CSS Text Level 3](https://www.w3.org/TR/css-text-3/#text-transform-property) | CSS allows full-width and full-size-kana. Since 4.6 |
|
||||
|line-height| [CSS Inline Layout Level 3](https://www.w3.org/TR/css-inline-3/#line-height-property) | Since 4.6 |
|
||||
|text-decoration-line| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-line-property) | |
|
||||
|text-decoration-color| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-color-property) | |
|
||||
|text-decoration-style| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-style-property) | CSS allows dashed and dotted |
|
||||
|
@@ -14,7 +14,7 @@ search_index = true
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable"
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
|
||||
[dependencies."Graphene-1.0"]
|
||||
name = "Graphene"
|
||||
|
@@ -137,6 +137,14 @@ capture phase, and key bindings locally, during the target phase.
|
||||
Under the hood, all shortcuts are represented as instances of `GtkShortcut`,
|
||||
and they are managed by `GtkShortcutController`.
|
||||
|
||||
## Text input
|
||||
|
||||
When actual text input is needed (i.e. not just keyboard shortcuts),
|
||||
input method support can be added to a widget by connecting an input
|
||||
method context and listening to its `::commit` signal. To create a new
|
||||
input method context, use gtk_im_multicontext_new(), to provide it with
|
||||
input, use gtk_event_controller_key_set_im_context().
|
||||
|
||||
## Event controllers and gestures
|
||||
|
||||
Event controllers are standalone objects that can perform
|
||||
|
@@ -27,9 +27,15 @@ expand_content_md_files = [
|
||||
'visual_index.md'
|
||||
]
|
||||
|
||||
gtk4_toml = configure_file(input: 'gtk4.toml.in', output: 'gtk4.toml', configuration: toml_conf)
|
||||
|
||||
if get_option('gtk_doc')
|
||||
gtk4_toml = configure_file(
|
||||
input: 'gtk4.toml.in',
|
||||
output: 'gtk4.toml',
|
||||
configuration: toml_conf,
|
||||
install: true,
|
||||
install_dir: docs_dir / 'gtk4',
|
||||
)
|
||||
|
||||
custom_target('gtk4-doc',
|
||||
input: [ gtk4_toml, gtk_gir[0] ],
|
||||
output: 'gtk4',
|
||||
|
@@ -3,11 +3,14 @@
|
||||
|
||||
// A map between namespaces and base URLs for their online documentation
|
||||
baseURLs = [
|
||||
[ 'Gdk', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://gnome.pages.gitlab.gnome.org/gtk/gsk4/' ],
|
||||
[ 'Gtk', 'https://gnome.pages.gitlab.gnome.org/gtk/gtk4/' ],
|
||||
[ 'Pango', 'https://gnome.pages/gitlab.gnome.org/pango/pango/' ],
|
||||
[ 'PangoCairo', 'https://gnome.pages.gitlab.gnome.org/pango/pangocairo/' ],
|
||||
[ 'GLib', 'https://docs.gtk.org/glib/' ],
|
||||
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
|
||||
[ 'Gio', 'https://docs.gtk.org/gio/' ],
|
||||
[ 'Gdk', 'https://docs.gtk.org/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://docs.gtk.org/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://docs.gtk.org/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://docs.gtk.org/gsk4/' ],
|
||||
[ 'Gtk', 'https://docs.gtk.org/gtk4/' ],
|
||||
[ 'Pango', 'https://docs.gtk.org/Pango/' ],
|
||||
[ 'PangoCairo', 'https://docs.gtk.org/PangoCairo/' ],
|
||||
]
|
||||
|
@@ -14,14 +14,19 @@ instructions, binary downloads, etc, can be found
|
||||
The Win32 GDK backend can be influenced with some additional environment
|
||||
variables.
|
||||
|
||||
### GDK_IGNORE_WINTAB
|
||||
### GDK_WIN32_TABLET_INPUT_API
|
||||
|
||||
If this variable is set, GTK doesn't use the Wintab API for tablet support.
|
||||
If this variable is set, it determines the API that GTK uses for tablet support.
|
||||
The possible values are:
|
||||
|
||||
### GDK_USE_WINTAB
|
||||
`none`
|
||||
: Disables tablet support
|
||||
|
||||
If this variable is set, GTK uses the Wintab API for tablet support.
|
||||
This is the default.
|
||||
`wintab`
|
||||
: Use the Wintab API
|
||||
|
||||
`winpointer`
|
||||
: Use the Windows Pointer Input Stack API. This is the default.
|
||||
|
||||
## Windows-specific handling of cursors
|
||||
|
||||
|
@@ -5,6 +5,10 @@ gidocgen = find_program('gi-docgen', required: get_option('gtk_doc'))
|
||||
|
||||
docs_dir = gtk_datadir / 'doc'
|
||||
|
||||
if get_option('gtk_doc') and not build_gir
|
||||
error('API reference requires introspection.')
|
||||
endif
|
||||
|
||||
subdir('gdk')
|
||||
subdir('gsk')
|
||||
subdir('gtk')
|
||||
|
@@ -603,8 +603,8 @@ bloat_pad_startup (GApplication *application)
|
||||
g_object_unref (icon);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
icon = G_ICON (gdk_pixbuf_new_from_resource ("/org/gtk/libgtk/icons/16x16/actions/folder-new.png", NULL));
|
||||
item = g_menu_item_new ("Pixbuf", NULL);
|
||||
icon = G_ICON (gdk_texture_new_from_resource ("/org/gtk/libgtk/icons/16x16/actions/folder-new.png"));
|
||||
item = g_menu_item_new ("Texture", NULL);
|
||||
g_menu_item_set_icon (item, icon);
|
||||
g_menu_append_item (menu, item);
|
||||
g_object_unref (item);
|
||||
|
50
examples/labels.js
Executable file
50
examples/labels.js
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env -S GI_TYPELIB_PATH=${PWD}/build/gtk:${GI_TYPELIB_PATH} LD_PRELOAD=${LD_PRELOAD}:${PWD}/build/gtk/libgtk-4.so gjs
|
||||
|
||||
imports.gi.versions['Gtk'] = '4.0';
|
||||
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
|
||||
const DemoWidget = GObject.registerClass({
|
||||
GTypeName: 'DemoWidget',
|
||||
}, class DemoWidget extends Gtk.Widget {
|
||||
|
||||
_init(params = {}) {
|
||||
super._init(params);
|
||||
|
||||
let layout_manager = new Gtk.GridLayout ();
|
||||
this.set_layout_manager (layout_manager);
|
||||
this.label1 = new Gtk.Label({ label: "Red",
|
||||
hexpand: true,
|
||||
vexpand: true });
|
||||
this.label1.set_parent (this);
|
||||
let child1 = layout_manager.get_layout_child (this.label1);
|
||||
child1.set_row (0);
|
||||
child1.set_column (0);
|
||||
|
||||
this.label2 = new Gtk.Label({ label: "Green",
|
||||
hexpand: true,
|
||||
vexpand: true });
|
||||
this.label2.set_parent (this);
|
||||
let child2 = layout_manager.get_layout_child (this.label2);
|
||||
child2.set_row (0);
|
||||
child2.set_column (1);
|
||||
}
|
||||
});
|
||||
|
||||
// Create a new application
|
||||
let app = new Gtk.Application({ application_id: 'org.gtk.exampleapp' });
|
||||
|
||||
// When the application is launched…
|
||||
app.connect('activate', () => {
|
||||
// … create a new window …
|
||||
let win = new Gtk.ApplicationWindow({ application: app });
|
||||
// … with a button in it …
|
||||
let widget = new DemoWidget();
|
||||
win.set_child(widget);
|
||||
win.present();
|
||||
});
|
||||
|
||||
// Run the application
|
||||
app.run([]);
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include <gdk/gdktextureprivate.h>
|
||||
#include "gdk-private.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
@@ -463,7 +464,7 @@ gdk_broadway_display_flush_in_idle (GdkDisplay *display)
|
||||
if (broadway_display->idle_flush_id == 0)
|
||||
{
|
||||
broadway_display->idle_flush_id = g_idle_add (flush_idle, g_object_ref (display));
|
||||
g_source_set_name_by_id (broadway_display->idle_flush_id, "[gtk] flush_idle");
|
||||
gdk_source_set_static_name_by_id (broadway_display->idle_flush_id, "[gtk] flush_idle");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -29,7 +29,7 @@ gboolean gdk_should_use_portal (void);
|
||||
|
||||
const char * gdk_get_startup_notification_id (void);
|
||||
|
||||
PangoDirection gdk_unichar_direction (gunichar ch);
|
||||
PangoDirection gdk_unichar_direction (gunichar ch) G_GNUC_CONST;
|
||||
PangoDirection gdk_find_base_dir (const char *text,
|
||||
int len);
|
||||
|
||||
@@ -57,4 +57,11 @@ guint gdk_parse_debug_var (const char *variable,
|
||||
# define g_memdup2(mem,size) g_memdup((mem),(size))
|
||||
#endif
|
||||
|
||||
void gdk_source_set_static_name_by_id (guint tag,
|
||||
const char *name);
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2, 69, 1)
|
||||
#define g_source_set_static_name(source, name) g_source_set_name ((source), (name))
|
||||
#endif
|
||||
|
||||
#endif /* __GDK__PRIVATE_H__ */
|
||||
|
18
gdk/gdk.c
18
gdk/gdk.c
@@ -127,10 +127,12 @@ static const GdkDebugKey gdk_debug_keys[] = {
|
||||
{ "gl-legacy", GDK_DEBUG_GL_LEGACY, "Use a legacy OpenGL context" },
|
||||
{ "gl-gles", GDK_DEBUG_GL_GLES, "Use a GLES OpenGL context" },
|
||||
{ "gl-debug", GDK_DEBUG_GL_DEBUG, "Insert debugging information in OpenGL" },
|
||||
{ "gl-egl", GDK_DEBUG_GL_EGL, "Use EGL on X11 or Windows" },
|
||||
{ "gl-glx", GDK_DEBUG_GL_GLX, "Use GLX on X11" },
|
||||
{ "gl-wgl", GDK_DEBUG_GL_WGL, "Use WGL on Windows" },
|
||||
{ "vulkan-disable", GDK_DEBUG_VULKAN_DISABLE, "Disable Vulkan support" },
|
||||
{ "vulkan-validate", GDK_DEBUG_VULKAN_VALIDATE, "Load the Vulkan validation layer" },
|
||||
{ "default-settings",GDK_DEBUG_DEFAULT_SETTINGS, "Force default values for xsettings" },
|
||||
{ "default-settings",GDK_DEBUG_DEFAULT_SETTINGS, "Force default values for xsettings", TRUE },
|
||||
};
|
||||
|
||||
|
||||
@@ -412,3 +414,17 @@ gdk_find_base_dir (const char *text,
|
||||
return dir;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_source_set_static_name_by_id (guint tag,
|
||||
const char *name)
|
||||
{
|
||||
GSource *source;
|
||||
|
||||
g_return_if_fail (tag > 0);
|
||||
|
||||
source = g_main_context_find_source_by_id (NULL, tag);
|
||||
if (source == NULL)
|
||||
return;
|
||||
|
||||
g_source_set_static_name (source, name);
|
||||
}
|
||||
|
@@ -50,7 +50,7 @@ cairo_region_t *
|
||||
gdk_cairo_region_create_from_surface
|
||||
(cairo_surface_t *surface);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DEPRECATED_IN_4_6_FOR(gdk_gl_texture_new)
|
||||
void gdk_cairo_draw_from_gl (cairo_t *cr,
|
||||
GdkSurface *surface,
|
||||
int source,
|
||||
|
@@ -635,7 +635,7 @@ gdk_clipboard_read_internal (GdkClipboard *clipboard,
|
||||
/**
|
||||
* gdk_clipboard_read_async:
|
||||
* @clipboard: a `GdkClipboard`
|
||||
* @mime_types: a %NULL-terminated array of mime types to choose from
|
||||
* @mime_types: (array zero-terminated=1): a %NULL-terminated array of mime types to choose from
|
||||
* @io_priority: the I/O priority of the request
|
||||
* @cancellable: (nullable): optional `GCancellable` object
|
||||
* @callback: (scope async): callback to call when the request is satisfied
|
||||
@@ -1253,9 +1253,15 @@ gdk_clipboard_set_content (GdkClipboard *clipboard,
|
||||
* @...: value contents conforming to @type
|
||||
*
|
||||
* Sets the clipboard to contain the value collected from the given varargs.
|
||||
*
|
||||
* Values should be passed the same way they are passed to other value
|
||||
* collecting APIs, such as [`method@GObject.Object.set`] or
|
||||
* [`id@g_signal_emit`].
|
||||
*
|
||||
* ```c
|
||||
* gdk_clipboard_set (clipboard, GTK_TYPE_TEXT_BUFFER, buffer);
|
||||
* gdk_clipboard_set (clipboard, GTK_TYPE_STRING, "Hello World");
|
||||
*
|
||||
* gdk_clipboard_set (clipboard, GDK_TYPE_TEXTURE, some_texture);
|
||||
* ```
|
||||
*/
|
||||
void
|
||||
|
@@ -25,6 +25,8 @@
|
||||
#include "filetransferportalprivate.h"
|
||||
#include "gdktexture.h"
|
||||
#include "gdkrgbaprivate.h"
|
||||
#include "loaders/gdkpngprivate.h"
|
||||
#include "loaders/gdktiffprivate.h"
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
@@ -553,6 +555,8 @@ gdk_content_deserialize_async (GInputStream *stream,
|
||||
Deserializer *deserializer;
|
||||
|
||||
g_return_if_fail (G_IS_INPUT_STREAM (stream));
|
||||
g_return_if_fail (mime_type != NULL);
|
||||
g_return_if_fail (G_TYPE_IS_VALUE_TYPE (type));
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
@@ -591,7 +595,10 @@ gdk_content_deserialize_finish (GAsyncResult *result,
|
||||
g_return_val_if_fail (GDK_IS_CONTENT_DESERIALIZER (result), FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
deserializer = GDK_CONTENT_DESERIALIZER (result);
|
||||
g_return_val_if_fail (G_VALUE_HOLDS (value, G_VALUE_TYPE (&deserializer->value)), FALSE);
|
||||
if (G_VALUE_TYPE (value) == 0)
|
||||
g_value_init (value, G_VALUE_TYPE (&deserializer->value));
|
||||
else
|
||||
g_return_val_if_fail (G_VALUE_HOLDS (value, G_VALUE_TYPE (&deserializer->value)), FALSE);
|
||||
|
||||
if (deserializer->error)
|
||||
{
|
||||
@@ -650,6 +657,56 @@ pixbuf_deserializer (GdkContentDeserializer *deserializer)
|
||||
deserializer);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_deserializer_finish (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer deserializer)
|
||||
{
|
||||
GOutputStream *stream = G_OUTPUT_STREAM (source);
|
||||
GBytes *bytes;
|
||||
GError *error = NULL;
|
||||
GdkTexture *texture = NULL;
|
||||
gssize written;
|
||||
|
||||
written = g_output_stream_splice_finish (stream, result, &error);
|
||||
if (written < 0)
|
||||
{
|
||||
gdk_content_deserializer_return_error (deserializer, error);
|
||||
return;
|
||||
}
|
||||
|
||||
bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (stream));
|
||||
|
||||
texture = gdk_texture_new_from_bytes (bytes, &error);
|
||||
g_bytes_unref (bytes);
|
||||
if (texture == NULL)
|
||||
{
|
||||
gdk_content_deserializer_return_error (deserializer, error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_value_take_object (gdk_content_deserializer_get_value (deserializer), texture);
|
||||
gdk_content_deserializer_return_success (deserializer);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_deserializer (GdkContentDeserializer *deserializer)
|
||||
{
|
||||
GOutputStream *output;
|
||||
|
||||
output = g_memory_output_stream_new_resizable ();
|
||||
|
||||
g_output_stream_splice_async (output,
|
||||
gdk_content_deserializer_get_input_stream (deserializer),
|
||||
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE
|
||||
| G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
|
||||
gdk_content_deserializer_get_priority (deserializer),
|
||||
gdk_content_deserializer_get_cancellable (deserializer),
|
||||
texture_deserializer_finish,
|
||||
deserializer);
|
||||
g_object_unref (output);
|
||||
}
|
||||
|
||||
static void
|
||||
string_deserializer_finish (GObject *source,
|
||||
GAsyncResult *result,
|
||||
@@ -858,48 +915,71 @@ init (void)
|
||||
|
||||
initialized = TRUE;
|
||||
|
||||
gdk_content_register_deserializer ("image/png",
|
||||
GDK_TYPE_TEXTURE,
|
||||
texture_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
gdk_content_register_deserializer ("image/tiff",
|
||||
GDK_TYPE_TEXTURE,
|
||||
texture_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
gdk_content_register_deserializer ("image/jpeg",
|
||||
GDK_TYPE_TEXTURE,
|
||||
texture_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
|
||||
formats = gdk_pixbuf_get_formats ();
|
||||
|
||||
/* Make sure png comes first */
|
||||
for (f = formats; f; f = f->next)
|
||||
{
|
||||
GdkPixbufFormat *fmt = f->data;
|
||||
char *name;
|
||||
|
||||
char *name;
|
||||
|
||||
name = gdk_pixbuf_format_get_name (fmt);
|
||||
if (g_str_equal (name, "png"))
|
||||
{
|
||||
formats = g_slist_delete_link (formats, f);
|
||||
formats = g_slist_prepend (formats, fmt);
|
||||
{
|
||||
formats = g_slist_delete_link (formats, f);
|
||||
formats = g_slist_prepend (formats, fmt);
|
||||
|
||||
g_free (name);
|
||||
|
||||
break;
|
||||
}
|
||||
g_free (name);
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
}
|
||||
|
||||
for (f = formats; f; f = f->next)
|
||||
{
|
||||
GdkPixbufFormat *fmt = f->data;
|
||||
char **mimes, **m;
|
||||
char *name;
|
||||
|
||||
name = gdk_pixbuf_format_get_name (fmt);
|
||||
mimes = gdk_pixbuf_format_get_mime_types (fmt);
|
||||
for (m = mimes; *m; m++)
|
||||
{
|
||||
gdk_content_register_deserializer (*m,
|
||||
GDK_TYPE_TEXTURE,
|
||||
pixbuf_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
{
|
||||
/* Turning pngs, jpegs and tiffs into textures is handled above */
|
||||
if (!g_str_equal (name, "png") &&
|
||||
!g_str_equal (name, "jpeg") &&
|
||||
!g_str_equal (name, "tiff"))
|
||||
gdk_content_register_deserializer (*m,
|
||||
GDK_TYPE_TEXTURE,
|
||||
pixbuf_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
gdk_content_register_deserializer (*m,
|
||||
GDK_TYPE_PIXBUF,
|
||||
pixbuf_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
g_strfreev (mimes);
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
g_slist_free (formats);
|
||||
|
@@ -179,6 +179,76 @@ gdk_content_formats_new_for_gtype (GType type)
|
||||
return gdk_content_formats_new_take (data, 1, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_content_formats_parse:
|
||||
* @string: the string to parse
|
||||
*
|
||||
* Parses the given @string into `GdkContentFormats` and
|
||||
* returns the formats.
|
||||
*
|
||||
* Strings printed via [method@Gdk.ContentFormats.to_string]
|
||||
* can be read in again successfully using this function.
|
||||
*
|
||||
* If @string does not describe valid content formats, %NULL
|
||||
* is returned.
|
||||
*
|
||||
* Returns: (nullable): the content formats if @string is valid
|
||||
*
|
||||
* Since: 4.4
|
||||
*/
|
||||
GdkContentFormats *
|
||||
gdk_content_formats_parse (const char *string)
|
||||
{
|
||||
GdkContentFormatsBuilder *builder;
|
||||
char **split;
|
||||
gsize i;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
|
||||
split = g_strsplit_set (string, "\t\n\f\r ", -1); /* same as g_ascii_isspace() */
|
||||
builder = gdk_content_formats_builder_new ();
|
||||
|
||||
/* first the GTypes */
|
||||
for (i = 0; split[i] != NULL; i++)
|
||||
{
|
||||
GType type;
|
||||
|
||||
if (split[i][0] == 0)
|
||||
continue;
|
||||
|
||||
type = g_type_from_name (split[i]);
|
||||
if (type != 0)
|
||||
gdk_content_formats_builder_add_gtype (builder, type);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* then the mime types */
|
||||
for (; split[i] != NULL; i++)
|
||||
{
|
||||
const char *mime_type;
|
||||
|
||||
if (split[i][0] == 0)
|
||||
continue;
|
||||
|
||||
mime_type = gdk_intern_mime_type (split[i]);
|
||||
if (mime_type)
|
||||
gdk_content_formats_builder_add_mime_type (builder, mime_type);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (split[i] != NULL)
|
||||
{
|
||||
g_strfreev (split);
|
||||
gdk_content_formats_builder_unref (builder);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_strfreev (split);
|
||||
return gdk_content_formats_builder_free_to_formats (builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_content_formats_ref:
|
||||
* @formats: a `GdkContentFormats`
|
||||
@@ -227,10 +297,8 @@ gdk_content_formats_unref (GdkContentFormats *formats)
|
||||
*
|
||||
* Prints the given @formats into a string for human consumption.
|
||||
*
|
||||
* This is meant for debugging and logging.
|
||||
*
|
||||
* The form of the representation may change at any time and is
|
||||
* not guaranteed to stay identical.
|
||||
* The result of this function can later be parsed with
|
||||
* [func@Gdk.ContentFormats.parse].
|
||||
*/
|
||||
void
|
||||
gdk_content_formats_print (GdkContentFormats *formats,
|
||||
@@ -241,20 +309,18 @@ gdk_content_formats_print (GdkContentFormats *formats,
|
||||
g_return_if_fail (formats != NULL);
|
||||
g_return_if_fail (string != NULL);
|
||||
|
||||
g_string_append (string, "{ ");
|
||||
for (i = 0; i < formats->n_gtypes; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
g_string_append (string, ", ");
|
||||
g_string_append (string, " ");
|
||||
g_string_append (string, g_type_name (formats->gtypes[i]));
|
||||
}
|
||||
for (i = 0; i < formats->n_mime_types; i++)
|
||||
{
|
||||
if (i > 0 || formats->n_gtypes > 0)
|
||||
g_string_append (string, ", ");
|
||||
g_string_append (string, " ");
|
||||
g_string_append (string, formats->mime_types[i]);
|
||||
}
|
||||
g_string_append (string, " }");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -263,6 +329,8 @@ gdk_content_formats_print (GdkContentFormats *formats,
|
||||
*
|
||||
* Prints the given @formats into a human-readable string.
|
||||
*
|
||||
* The resulting string can be parsed with [func@Gdk.ContentFormats.parse].
|
||||
*
|
||||
* This is a small wrapper around [method@Gdk.ContentFormats.print]
|
||||
* to help when debugging.
|
||||
*
|
||||
|
@@ -40,6 +40,8 @@ GdkContentFormats * gdk_content_formats_new (const char
|
||||
guint n_mime_types);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkContentFormats * gdk_content_formats_new_for_gtype (GType type);
|
||||
GDK_AVAILABLE_IN_4_4
|
||||
GdkContentFormats * gdk_content_formats_parse (const char *string);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkContentFormats * gdk_content_formats_ref (GdkContentFormats *formats);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
@@ -80,7 +80,7 @@ gdk_content_provider_value_get_value (GdkContentProvider *provider,
|
||||
{
|
||||
GdkContentProviderValue *content = GDK_CONTENT_PROVIDER_VALUE (provider);
|
||||
|
||||
if (G_VALUE_HOLDS (value, G_VALUE_TYPE (&content->value)))
|
||||
if (G_VALUE_HOLDS (&content->value, G_VALUE_TYPE (value)))
|
||||
{
|
||||
g_value_copy (&content->value, value);
|
||||
return TRUE;
|
||||
|
@@ -26,6 +26,10 @@
|
||||
#include "filetransferportalprivate.h"
|
||||
#include "gdktextureprivate.h"
|
||||
#include "gdkrgba.h"
|
||||
#include "loaders/gdkpngprivate.h"
|
||||
#include "loaders/gdktiffprivate.h"
|
||||
#include "loaders/gdkjpegprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <string.h>
|
||||
@@ -606,6 +610,7 @@ gdk_content_serialize_finish (GAsyncResult *result,
|
||||
|
||||
/*** SERIALIZERS ***/
|
||||
|
||||
|
||||
static void
|
||||
pixbuf_serializer_finish (GObject *source,
|
||||
GAsyncResult *res,
|
||||
@@ -658,6 +663,77 @@ pixbuf_serializer (GdkContentSerializer *serializer)
|
||||
g_object_unref (pixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_serializer_finish (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkContentSerializer *serializer = GDK_CONTENT_SERIALIZER (source);
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_task_propagate_boolean (G_TASK (res), &error))
|
||||
gdk_content_serializer_return_error (serializer, error);
|
||||
else
|
||||
gdk_content_serializer_return_success (serializer);
|
||||
}
|
||||
|
||||
static void
|
||||
serialize_texture_in_thread (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GdkContentSerializer *serializer = source_object;
|
||||
const GValue *value;
|
||||
GdkTexture *texture;
|
||||
GBytes *bytes = NULL;
|
||||
GError *error = NULL;
|
||||
gboolean result = FALSE;
|
||||
GInputStream *input;
|
||||
gssize spliced;
|
||||
|
||||
value = gdk_content_serializer_get_value (serializer);
|
||||
texture = g_value_get_object (value);
|
||||
|
||||
if (strcmp (gdk_content_serializer_get_mime_type (serializer), "image/png") == 0)
|
||||
bytes = gdk_save_png (texture);
|
||||
else if (strcmp (gdk_content_serializer_get_mime_type (serializer), "image/tiff") == 0)
|
||||
bytes = gdk_save_tiff (texture);
|
||||
else if (strcmp (gdk_content_serializer_get_mime_type (serializer), "image/jpeg") == 0)
|
||||
bytes = gdk_save_jpeg (texture);
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
|
||||
input = g_memory_input_stream_new_from_bytes (bytes);
|
||||
spliced = g_output_stream_splice (gdk_content_serializer_get_output_stream (serializer),
|
||||
input,
|
||||
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
|
||||
gdk_content_serializer_get_cancellable (serializer),
|
||||
&error);
|
||||
g_object_unref (input);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
result = spliced != -1;
|
||||
|
||||
if (result)
|
||||
g_task_return_boolean (task, result);
|
||||
else
|
||||
g_task_return_error (task, error);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_serializer (GdkContentSerializer *serializer)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (serializer,
|
||||
gdk_content_serializer_get_cancellable (serializer),
|
||||
texture_serializer_finish,
|
||||
NULL);
|
||||
g_task_run_in_thread (task, serialize_texture_in_thread);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
string_serializer_finish (GObject *source,
|
||||
GAsyncResult *result,
|
||||
@@ -877,51 +953,72 @@ init (void)
|
||||
|
||||
initialized = TRUE;
|
||||
|
||||
gdk_content_register_serializer (GDK_TYPE_TEXTURE,
|
||||
"image/png",
|
||||
texture_serializer,
|
||||
NULL, NULL);
|
||||
|
||||
gdk_content_register_serializer (GDK_TYPE_TEXTURE,
|
||||
"image/tiff",
|
||||
texture_serializer,
|
||||
NULL, NULL);
|
||||
|
||||
gdk_content_register_serializer (GDK_TYPE_TEXTURE,
|
||||
"image/jpeg",
|
||||
texture_serializer,
|
||||
NULL, NULL);
|
||||
|
||||
formats = gdk_pixbuf_get_formats ();
|
||||
|
||||
/* Make sure png comes first */
|
||||
for (f = formats; f; f = f->next)
|
||||
{
|
||||
GdkPixbufFormat *fmt = f->data;
|
||||
char *name;
|
||||
|
||||
char *name;
|
||||
|
||||
name = gdk_pixbuf_format_get_name (fmt);
|
||||
if (g_str_equal (name, "png"))
|
||||
{
|
||||
formats = g_slist_delete_link (formats, f);
|
||||
formats = g_slist_prepend (formats, fmt);
|
||||
{
|
||||
formats = g_slist_delete_link (formats, f);
|
||||
formats = g_slist_prepend (formats, fmt);
|
||||
|
||||
g_free (name);
|
||||
|
||||
break;
|
||||
}
|
||||
g_free (name);
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
}
|
||||
|
||||
for (f = formats; f; f = f->next)
|
||||
{
|
||||
GdkPixbufFormat *fmt = f->data;
|
||||
char **mimes, **m;
|
||||
char *name;
|
||||
|
||||
if (!gdk_pixbuf_format_is_writable (fmt))
|
||||
continue;
|
||||
continue;
|
||||
|
||||
name = gdk_pixbuf_format_get_name (fmt);
|
||||
mimes = gdk_pixbuf_format_get_mime_types (fmt);
|
||||
for (m = mimes; *m; m++)
|
||||
{
|
||||
gdk_content_register_serializer (GDK_TYPE_TEXTURE,
|
||||
*m,
|
||||
pixbuf_serializer,
|
||||
gdk_pixbuf_format_get_name (fmt),
|
||||
g_free);
|
||||
{
|
||||
/* Turning textures into pngs, tiffs or jpegs is handled above */
|
||||
if (!g_str_equal (name, "png") &&
|
||||
!g_str_equal (name, "tiff") &&
|
||||
!g_str_equal (name, "jpeg"))
|
||||
gdk_content_register_serializer (GDK_TYPE_TEXTURE,
|
||||
*m,
|
||||
pixbuf_serializer,
|
||||
gdk_pixbuf_format_get_name (fmt),
|
||||
g_free);
|
||||
gdk_content_register_serializer (GDK_TYPE_PIXBUF,
|
||||
*m,
|
||||
pixbuf_serializer,
|
||||
gdk_pixbuf_format_get_name (fmt),
|
||||
g_free);
|
||||
}
|
||||
}
|
||||
g_strfreev (mimes);
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
g_slist_free (formats);
|
||||
|
@@ -41,10 +41,12 @@ typedef enum {
|
||||
GDK_DEBUG_GL_LEGACY = 1 << 15,
|
||||
GDK_DEBUG_GL_GLES = 1 << 16,
|
||||
GDK_DEBUG_GL_DEBUG = 1 << 17,
|
||||
GDK_DEBUG_GL_GLX = 1 << 18,
|
||||
GDK_DEBUG_VULKAN_DISABLE = 1 << 19,
|
||||
GDK_DEBUG_VULKAN_VALIDATE = 1 << 20,
|
||||
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 21
|
||||
GDK_DEBUG_GL_EGL = 1 << 18,
|
||||
GDK_DEBUG_GL_GLX = 1 << 19,
|
||||
GDK_DEBUG_GL_WGL = 1 << 20,
|
||||
GDK_DEBUG_VULKAN_DISABLE = 1 << 21,
|
||||
GDK_DEBUG_VULKAN_VALIDATE = 1 << 22,
|
||||
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 23,
|
||||
} GdkDebugFlags;
|
||||
|
||||
extern guint _gdk_debug_flags;
|
||||
|
216
gdk/gdkdisplay.c
216
gdk/gdkdisplay.c
@@ -77,6 +77,23 @@ enum {
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
typedef struct _GdkDisplayPrivate GdkDisplayPrivate;
|
||||
|
||||
struct _GdkDisplayPrivate {
|
||||
/* The base context that all other contexts inherit from.
|
||||
* This context is never exposed to public API and is
|
||||
* allowed to have a %NULL surface.
|
||||
*/
|
||||
GdkGLContext *gl_context;
|
||||
GError *gl_error;
|
||||
|
||||
guint rgba : 1;
|
||||
guint composited : 1;
|
||||
guint input_shapes : 1;
|
||||
|
||||
GdkDebugFlags debug_flags;
|
||||
};
|
||||
|
||||
static void gdk_display_dispose (GObject *object);
|
||||
static void gdk_display_finalize (GObject *object);
|
||||
|
||||
@@ -85,7 +102,7 @@ static GdkAppLaunchContext *gdk_display_real_get_app_launch_context (GdkDisplay
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
G_DEFINE_TYPE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gdk_display_get_property (GObject *object,
|
||||
@@ -119,10 +136,14 @@ gdk_display_real_make_default (GdkDisplay *display)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_real_opened (GdkDisplay *display)
|
||||
static GdkGLContext *
|
||||
gdk_display_default_init_gl (GdkDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
_gdk_display_manager_add_display (gdk_display_manager_get (), display);
|
||||
g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("The current backend does not support OpenGL"));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GdkSeat *
|
||||
@@ -134,6 +155,12 @@ gdk_display_real_get_default_seat (GdkDisplay *display)
|
||||
return display->seats->data;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_real_opened (GdkDisplay *display)
|
||||
{
|
||||
_gdk_display_manager_add_display (gdk_display_manager_get (), display);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_class_init (GdkDisplayClass *class)
|
||||
{
|
||||
@@ -143,10 +170,11 @@ gdk_display_class_init (GdkDisplayClass *class)
|
||||
object_class->dispose = gdk_display_dispose;
|
||||
object_class->get_property = gdk_display_get_property;
|
||||
|
||||
class->get_app_launch_context = gdk_display_real_get_app_launch_context;
|
||||
class->opened = gdk_display_real_opened;
|
||||
class->make_default = gdk_display_real_make_default;
|
||||
class->get_app_launch_context = gdk_display_real_get_app_launch_context;
|
||||
class->init_gl = gdk_display_default_init_gl;
|
||||
class->get_default_seat = gdk_display_real_get_default_seat;
|
||||
class->opened = gdk_display_real_opened;
|
||||
|
||||
/**
|
||||
* GdkDisplay:composited: (attributes org.gtk.Property.get=gdk_display_is_composited)
|
||||
@@ -294,6 +322,8 @@ free_device_grabs_foreach (gpointer key,
|
||||
static void
|
||||
gdk_display_init (GdkDisplay *display)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
display->double_click_time = 250;
|
||||
display->double_click_distance = 5;
|
||||
|
||||
@@ -304,22 +334,26 @@ gdk_display_init (GdkDisplay *display)
|
||||
|
||||
g_queue_init (&display->queued_events);
|
||||
|
||||
display->debug_flags = _gdk_debug_flags;
|
||||
priv->debug_flags = _gdk_debug_flags;
|
||||
|
||||
display->composited = TRUE;
|
||||
display->rgba = TRUE;
|
||||
display->input_shapes = TRUE;
|
||||
priv->composited = TRUE;
|
||||
priv->rgba = TRUE;
|
||||
priv->input_shapes = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_dispose (GObject *object)
|
||||
{
|
||||
GdkDisplay *display = GDK_DISPLAY (object);
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
_gdk_display_manager_remove_display (gdk_display_manager_get (), display);
|
||||
|
||||
g_queue_clear (&display->queued_events);
|
||||
|
||||
g_clear_object (&priv->gl_context);
|
||||
g_clear_error (&priv->gl_error);
|
||||
|
||||
G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
@@ -998,21 +1032,25 @@ gdk_display_get_primary_clipboard (GdkDisplay *display)
|
||||
gboolean
|
||||
gdk_display_supports_input_shapes (GdkDisplay *display)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
|
||||
|
||||
return display->input_shapes;
|
||||
return priv->input_shapes;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_set_input_shapes (GdkDisplay *display,
|
||||
gboolean input_shapes)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_if_fail (GDK_IS_DISPLAY (display));
|
||||
|
||||
if (display->input_shapes == input_shapes)
|
||||
if (priv->input_shapes == input_shapes)
|
||||
return;
|
||||
|
||||
display->input_shapes = input_shapes;
|
||||
priv->input_shapes = input_shapes;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (display), props[PROP_INPUT_SHAPES]);
|
||||
}
|
||||
@@ -1157,32 +1195,136 @@ gdk_display_get_keymap (GdkDisplay *display)
|
||||
return GDK_DISPLAY_GET_CLASS (display)->get_keymap (display);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_display_make_gl_context_current:
|
||||
* @display: a `GdkDisplay`
|
||||
* @context: (optional): a `GdkGLContext`
|
||||
*
|
||||
* Makes the given @context the current GL context, or unsets
|
||||
* the current GL context if @context is %NULL.
|
||||
*/
|
||||
gboolean
|
||||
gdk_display_make_gl_context_current (GdkDisplay *display,
|
||||
GdkGLContext *context)
|
||||
static void
|
||||
gdk_display_init_gl (GdkDisplay *self)
|
||||
{
|
||||
return GDK_DISPLAY_GET_CLASS (display)->make_gl_context_current (display, context);
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
|
||||
GdkGLContext *context;
|
||||
gint64 before G_GNUC_UNUSED;
|
||||
gint64 before2 G_GNUC_UNUSED;
|
||||
|
||||
before = GDK_PROFILER_CURRENT_TIME;
|
||||
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (self, GL_DISABLE))
|
||||
{
|
||||
g_set_error_literal (&priv->gl_error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("GL support disabled via GDK_DEBUG"));
|
||||
return;
|
||||
}
|
||||
|
||||
context = GDK_DISPLAY_GET_CLASS (self)->init_gl (self, &priv->gl_error);
|
||||
if (context == NULL)
|
||||
return;
|
||||
|
||||
before2 = GDK_PROFILER_CURRENT_TIME;
|
||||
|
||||
if (!gdk_gl_context_realize (context, &priv->gl_error))
|
||||
{
|
||||
g_object_unref (context);
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_profiler_end_mark (before2, "realize OpenGL context", NULL);
|
||||
|
||||
/* Only assign after realize, so GdkGLContext::realize() can use
|
||||
* gdk_display_get_gl_context() == NULL to differentiate between
|
||||
* the display's context and any other context.
|
||||
*/
|
||||
priv->gl_context = context;
|
||||
|
||||
gdk_profiler_end_mark (before, "initialize OpenGL", NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_display_prepare_gl:
|
||||
* @self: a `GdkDisplay`
|
||||
* @error: return location for a `GError`
|
||||
*
|
||||
* Checks that OpenGL is available for @self and ensures that it is
|
||||
* properly initialized.
|
||||
* When this fails, an @error will be set describing the error and this
|
||||
* function returns %FALSE.
|
||||
*
|
||||
* Note that even if this function succeeds, creating a `GdkGLContext`
|
||||
* may still fail.
|
||||
*
|
||||
* This function is idempotent. Calling it multiple times will just
|
||||
* return the same value or error.
|
||||
*
|
||||
* You never need to call this function, GDK will call it automatically
|
||||
* as needed. But you can use it as a check when setting up code that
|
||||
* might make use of OpenGL.
|
||||
*
|
||||
* Returns: %TRUE if the display supports OpenGL
|
||||
*
|
||||
* Since: 4.4
|
||||
**/
|
||||
gboolean
|
||||
gdk_display_prepare_gl (GdkDisplay *self,
|
||||
GError **error)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (self), FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (priv->gl_context)
|
||||
return TRUE;
|
||||
|
||||
if (priv->gl_error != NULL)
|
||||
{
|
||||
if (error)
|
||||
*error = g_error_copy (priv->gl_error);
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gdk_display_init_gl (self);
|
||||
|
||||
/* try again */
|
||||
}
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_display_get_gl_context:
|
||||
* @self: the `GdkDisplay`
|
||||
*
|
||||
* Gets the GL context returned from [vfunc@Gdk.Display.init_gl]
|
||||
* previously.
|
||||
*
|
||||
* If that function has not been called yet or did fail, %NULL is
|
||||
* returned.
|
||||
* Call [method@Gdk.Display.prepare_gl] to avoid this.
|
||||
*
|
||||
* Returns: The `GdkGLContext`
|
||||
*/
|
||||
GdkGLContext *
|
||||
gdk_display_get_gl_context (GdkDisplay *self)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
|
||||
|
||||
return priv->gl_context;
|
||||
}
|
||||
|
||||
GdkDebugFlags
|
||||
gdk_display_get_debug_flags (GdkDisplay *display)
|
||||
{
|
||||
return display ? display->debug_flags : _gdk_debug_flags;
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
return display ? priv->debug_flags : _gdk_debug_flags;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_set_debug_flags (GdkDisplay *display,
|
||||
GdkDebugFlags flags)
|
||||
{
|
||||
display->debug_flags = flags;
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
priv->debug_flags = flags;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1207,21 +1349,25 @@ gdk_display_set_debug_flags (GdkDisplay *display,
|
||||
gboolean
|
||||
gdk_display_is_composited (GdkDisplay *display)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
|
||||
|
||||
return display->composited;
|
||||
return priv->composited;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_set_composited (GdkDisplay *display,
|
||||
gboolean composited)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_if_fail (GDK_IS_DISPLAY (display));
|
||||
|
||||
if (display->composited == composited)
|
||||
if (priv->composited == composited)
|
||||
return;
|
||||
|
||||
display->composited = composited;
|
||||
priv->composited = composited;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (display), props[PROP_COMPOSITED]);
|
||||
}
|
||||
@@ -1248,21 +1394,25 @@ gdk_display_set_composited (GdkDisplay *display,
|
||||
gboolean
|
||||
gdk_display_is_rgba (GdkDisplay *display)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
|
||||
|
||||
return display->rgba;
|
||||
return priv->rgba;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_set_rgba (GdkDisplay *display,
|
||||
gboolean rgba)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_if_fail (GDK_IS_DISPLAY (display));
|
||||
|
||||
if (display->rgba == rgba)
|
||||
if (priv->rgba == rgba)
|
||||
return;
|
||||
|
||||
display->rgba = rgba;
|
||||
priv->rgba = rgba;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (display), props[PROP_RGBA]);
|
||||
}
|
||||
|
@@ -68,6 +68,10 @@ gboolean gdk_display_is_rgba (GdkDisplay *display);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_display_supports_input_shapes (GdkDisplay *display);
|
||||
|
||||
GDK_AVAILABLE_IN_4_4
|
||||
gboolean gdk_display_prepare_gl (GdkDisplay *self,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay *gdk_display_get_default (void);
|
||||
|
||||
|
@@ -102,11 +102,6 @@ struct _GdkDisplay
|
||||
|
||||
guint vulkan_refcount;
|
||||
#endif /* GDK_RENDERING_VULKAN */
|
||||
guint rgba : 1;
|
||||
guint composited : 1;
|
||||
guint input_shapes : 1;
|
||||
|
||||
GdkDebugFlags debug_flags;
|
||||
|
||||
GList *seats;
|
||||
};
|
||||
@@ -145,8 +140,8 @@ struct _GdkDisplayClass
|
||||
|
||||
GdkKeymap * (*get_keymap) (GdkDisplay *display);
|
||||
|
||||
gboolean (*make_gl_context_current) (GdkDisplay *display,
|
||||
GdkGLContext *context);
|
||||
GdkGLContext * (*init_gl) (GdkDisplay *display,
|
||||
GError **error);
|
||||
|
||||
GdkSeat * (*get_default_seat) (GdkDisplay *display);
|
||||
|
||||
@@ -211,8 +206,7 @@ GdkSurface * gdk_display_create_surface (GdkDisplay *display
|
||||
int width,
|
||||
int height);
|
||||
|
||||
gboolean gdk_display_make_gl_context_current (GdkDisplay *display,
|
||||
GdkGLContext *context);
|
||||
GdkGLContext * gdk_display_get_gl_context (GdkDisplay *display);
|
||||
|
||||
void gdk_display_set_rgba (GdkDisplay *display,
|
||||
gboolean rgba);
|
||||
|
@@ -69,7 +69,7 @@ GDK_AVAILABLE_IN_ALL
|
||||
GdkDragAction gdk_drag_get_selected_action (GdkDrag *drag);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_drag_action_is_unique (GdkDragAction action);
|
||||
gboolean gdk_drag_action_is_unique (GdkDragAction action) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDrag * gdk_drag_begin (GdkSurface *surface,
|
||||
|
@@ -43,6 +43,7 @@
|
||||
typedef struct _GdkDrawContextPrivate GdkDrawContextPrivate;
|
||||
|
||||
struct _GdkDrawContextPrivate {
|
||||
GdkDisplay *display;
|
||||
GdkSurface *surface;
|
||||
|
||||
cairo_region_t *frame_region;
|
||||
@@ -77,6 +78,7 @@ gdk_draw_context_dispose (GObject *gobject)
|
||||
priv->surface->draw_contexts = g_slist_remove (priv->surface->draw_contexts, context);
|
||||
g_clear_object (&priv->surface);
|
||||
}
|
||||
g_clear_object (&priv->display);
|
||||
|
||||
G_OBJECT_CLASS (gdk_draw_context_parent_class)->dispose (gobject);
|
||||
}
|
||||
@@ -92,10 +94,31 @@ gdk_draw_context_set_property (GObject *gobject,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DISPLAY:
|
||||
if (priv->display != NULL)
|
||||
{
|
||||
g_assert (g_value_get_object (value) == NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->display = g_value_dup_object (value);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_SURFACE:
|
||||
priv->surface = g_value_dup_object (value);
|
||||
g_assert (priv->surface != NULL);
|
||||
priv->surface->draw_contexts = g_slist_prepend (priv->surface->draw_contexts, context);
|
||||
if (priv->surface)
|
||||
{
|
||||
priv->surface->draw_contexts = g_slist_prepend (priv->surface->draw_contexts, context);
|
||||
if (priv->display)
|
||||
{
|
||||
g_assert (priv->display == gdk_surface_get_display (priv->surface));
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->display = g_object_ref (gdk_surface_get_display (priv->surface));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -148,7 +171,8 @@ gdk_draw_context_class_init (GdkDrawContextClass *klass)
|
||||
P_("Display"),
|
||||
P_("The GDK display used to create the context"),
|
||||
GDK_TYPE_DISPLAY,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
@@ -228,7 +252,7 @@ gdk_draw_context_get_display (GdkDrawContext *context)
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DRAW_CONTEXT (context), NULL);
|
||||
|
||||
return priv->surface ? gdk_surface_get_display (priv->surface) : NULL;
|
||||
return priv->display;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkframeclockprivate.h"
|
||||
#include "gdk.h"
|
||||
#include "gdk-private.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
@@ -307,12 +308,15 @@ maybe_start_idle (GdkFrameClockIdle *clock_idle,
|
||||
|
||||
if (priv->flush_idle_id == 0 && RUN_FLUSH_IDLE (priv))
|
||||
{
|
||||
GSource *source;
|
||||
|
||||
priv->flush_idle_id = g_timeout_add_full (GDK_PRIORITY_EVENTS + 1,
|
||||
min_interval,
|
||||
gdk_frame_clock_flush_idle,
|
||||
g_object_ref (clock_idle),
|
||||
(GDestroyNotify) g_object_unref);
|
||||
g_source_set_name_by_id (priv->flush_idle_id, "[gtk] gdk_frame_clock_flush_idle");
|
||||
source = g_main_context_find_source_by_id (NULL, priv->flush_idle_id);
|
||||
g_source_set_static_name (source, "[gtk] gdk_frame_clock_flush_idle");
|
||||
}
|
||||
|
||||
if (!priv->in_paint_idle &&
|
||||
@@ -324,7 +328,7 @@ maybe_start_idle (GdkFrameClockIdle *clock_idle,
|
||||
gdk_frame_clock_paint_idle,
|
||||
g_object_ref (clock_idle),
|
||||
(GDestroyNotify) g_object_unref);
|
||||
g_source_set_name_by_id (priv->paint_idle_id, "[gtk] gdk_frame_clock_paint_idle");
|
||||
gdk_source_set_static_name_by_id (priv->paint_idle_id, "[gtk] gdk_frame_clock_paint_idle");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -301,7 +301,7 @@ gdk_gl_texture_quads (GdkGLContext *paint_context,
|
||||
* @width: The width of the region to draw
|
||||
* @height: The height of the region to draw
|
||||
*
|
||||
* The main way to draw GL content in GTK.
|
||||
* The main way to not draw GL content in GTK.
|
||||
*
|
||||
* It takes a render buffer ID (@source_type == GL_RENDERBUFFER) or a texture
|
||||
* id (@source_type == GL_TEXTURE) and draws it onto @cr with an OVER operation,
|
||||
@@ -319,6 +319,12 @@ gdk_gl_texture_quads (GdkGLContext *paint_context,
|
||||
* with alpha components, so make sure you use GL_TEXTURE if using alpha.
|
||||
*
|
||||
* Calling this may change the current GL context.
|
||||
*
|
||||
* Deprecated: 4.6: The function is overly complex and produces broken output
|
||||
* in various combinations of arguments. If you want to draw with GL textures
|
||||
* in GTK, use [ctor@Gdk.GLTexture.new]; if you want to use that texture in
|
||||
* Cairo, use [method@Gdk.Texture.download] to download the data into a Cairo
|
||||
* image surface.
|
||||
*/
|
||||
void
|
||||
gdk_cairo_draw_from_gl (cairo_t *cr,
|
||||
|
@@ -89,8 +89,6 @@
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
typedef struct {
|
||||
GdkGLContext *shared_context;
|
||||
|
||||
int major;
|
||||
int minor;
|
||||
int gl_version;
|
||||
@@ -127,7 +125,28 @@ G_DEFINE_QUARK (gdk-gl-error-quark, gdk_gl_error)
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkGLContext, gdk_gl_context, GDK_TYPE_DRAW_CONTEXT)
|
||||
|
||||
static GPrivate thread_current_context = G_PRIVATE_INIT (g_object_unref);
|
||||
typedef struct _MaskedContext MaskedContext;
|
||||
|
||||
static inline MaskedContext *
|
||||
mask_context (GdkGLContext *context,
|
||||
gboolean surfaceless)
|
||||
{
|
||||
return (MaskedContext *) GSIZE_TO_POINTER (GPOINTER_TO_SIZE (context) | (surfaceless ? 1 : 0));
|
||||
}
|
||||
|
||||
static inline GdkGLContext *
|
||||
unmask_context (MaskedContext *mask)
|
||||
{
|
||||
return GDK_GL_CONTEXT (GSIZE_TO_POINTER (GPOINTER_TO_SIZE (mask) & ~(gsize) 1));
|
||||
}
|
||||
|
||||
static void
|
||||
unref_unmasked (gpointer data)
|
||||
{
|
||||
g_object_unref (unmask_context (data));
|
||||
}
|
||||
|
||||
static GPrivate thread_current_context = G_PRIVATE_INIT (unref_unmasked);
|
||||
|
||||
static void
|
||||
gdk_gl_context_clear_old_updated_area (GdkGLContext *context)
|
||||
@@ -144,17 +163,14 @@ static void
|
||||
gdk_gl_context_dispose (GObject *gobject)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (gobject);
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
GdkGLContext *current;
|
||||
MaskedContext *current;
|
||||
|
||||
gdk_gl_context_clear_old_updated_area (context);
|
||||
|
||||
current = g_private_get (&thread_current_context);
|
||||
if (current == context)
|
||||
if (unmask_context (current) == context)
|
||||
g_private_replace (&thread_current_context, NULL);
|
||||
|
||||
g_clear_object (&priv->shared_context);
|
||||
|
||||
G_OBJECT_CLASS (gdk_gl_context_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
@@ -174,17 +190,10 @@ gdk_gl_context_set_property (GObject *gobject,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private ((GdkGLContext *) gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SHARED_CONTEXT:
|
||||
{
|
||||
GdkGLContext *context = g_value_get_object (value);
|
||||
|
||||
if (context != NULL)
|
||||
priv->shared_context = g_object_ref (context);
|
||||
}
|
||||
g_assert (g_value_get_object (value) == NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -198,12 +207,10 @@ gdk_gl_context_get_property (GObject *gobject,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private ((GdkGLContext *) gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SHARED_CONTEXT:
|
||||
g_value_set_object (value, priv->shared_context);
|
||||
g_value_set_object (value, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -222,64 +229,83 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
guchar *copy = NULL;
|
||||
guint gl_format;
|
||||
guint gl_type;
|
||||
guint bpp;
|
||||
GLint gl_internalformat;
|
||||
GLint gl_format;
|
||||
GLint gl_type;
|
||||
gsize bpp;
|
||||
|
||||
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
|
||||
|
||||
if (priv->use_es)
|
||||
if (!priv->use_es && data_format == GDK_MEMORY_DEFAULT) /* Cairo surface format */
|
||||
{
|
||||
/* GLES only supports rgba, so convert if necessary */
|
||||
if (data_format != GDK_MEMORY_R8G8B8A8_PREMULTIPLIED)
|
||||
{
|
||||
copy = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (copy, width * 4,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
data, stride, data_format,
|
||||
width, height);
|
||||
stride = width * 4;
|
||||
data = copy;
|
||||
}
|
||||
|
||||
bpp = 4;
|
||||
gl_internalformat = GL_RGBA8;
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R8G8B8) /* Pixmap non-alpha data */
|
||||
{
|
||||
gl_internalformat = GL_RGBA8;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else if (priv->use_es && data_format == GDK_MEMORY_B8G8R8)
|
||||
{
|
||||
gl_internalformat = GL_RGBA8;
|
||||
gl_format = GL_BGR;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R16G16B16)
|
||||
{
|
||||
gl_internalformat = GL_RGBA16;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_SHORT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R16G16B16A16_PREMULTIPLIED)
|
||||
{
|
||||
gl_internalformat = GL_RGBA16;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_SHORT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R16G16B16_FLOAT)
|
||||
{
|
||||
gl_internalformat = GL_RGB16F;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_HALF_FLOAT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED)
|
||||
{
|
||||
gl_internalformat = GL_RGBA16F;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_HALF_FLOAT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R32G32B32_FLOAT)
|
||||
{
|
||||
gl_internalformat = GL_RGB32F;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_FLOAT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED)
|
||||
{
|
||||
gl_internalformat = GL_RGBA32F;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_FLOAT;
|
||||
}
|
||||
else /* Fall-back, convert to GLES format */
|
||||
{
|
||||
copy = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (copy, width * 4,
|
||||
GDK_MEMORY_CONVERT_GLES_RGBA,
|
||||
data, stride, data_format,
|
||||
width, height);
|
||||
data_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
stride = width * 4;
|
||||
data = copy;
|
||||
gl_internalformat = GL_RGBA8;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data_format == GDK_MEMORY_DEFAULT) /* Cairo surface format */
|
||||
{
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
bpp = 4;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R8G8B8) /* Pixmap non-alpha data */
|
||||
{
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
bpp = 3;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_B8G8R8)
|
||||
{
|
||||
gl_format = GL_BGR;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
bpp = 3;
|
||||
}
|
||||
else /* Fall-back, convert to cairo-surface-format */
|
||||
{
|
||||
copy = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (copy, width * 4,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
data, stride, data_format,
|
||||
width, height);
|
||||
stride = width * 4;
|
||||
bpp = 4;
|
||||
data = copy;
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
}
|
||||
}
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (data_format);
|
||||
|
||||
/* GL_UNPACK_ROW_LENGTH is available on desktop GL, OpenGL ES >= 3.0, or if
|
||||
* the GL_EXT_unpack_subimage extension for OpenGL ES 2.0 is available
|
||||
@@ -288,7 +314,7 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
|
||||
{
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, gl_format, gl_type, data);
|
||||
glTexImage2D (texture_target, 0, gl_internalformat, width, height, 0, gl_format, gl_type, data);
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
|
||||
}
|
||||
else if ((!priv->use_es ||
|
||||
@@ -296,14 +322,14 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
|
||||
{
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, stride / bpp);
|
||||
|
||||
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, gl_format, gl_type, data);
|
||||
glTexImage2D (texture_target, 0, gl_internalformat, width, height, 0, gl_format, gl_type, data);
|
||||
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, gl_format, gl_type, NULL);
|
||||
glTexImage2D (texture_target, 0, gl_internalformat, width, height, 0, gl_format, gl_type, NULL);
|
||||
for (i = 0; i < height; i++)
|
||||
glTexSubImage2D (texture_target, 0, 0, i, width, 1, gl_format, gl_type, data + (i * stride));
|
||||
}
|
||||
@@ -333,23 +359,27 @@ gdk_gl_context_real_get_damage (GdkGLContext *context)
|
||||
});
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_gl_context_real_is_shared (GdkGLContext *self,
|
||||
GdkGLContext *other)
|
||||
{
|
||||
if (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (self)) != gdk_draw_context_get_display (GDK_DRAW_CONTEXT (other)))
|
||||
return FALSE;
|
||||
|
||||
/* XXX: Should we check es or legacy here? */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
|
||||
GdkSurface *surface;
|
||||
GdkGLContext *shared;
|
||||
cairo_region_t *damage;
|
||||
int ww, wh;
|
||||
|
||||
shared = gdk_gl_context_get_shared_context (context);
|
||||
if (shared)
|
||||
{
|
||||
GDK_DRAW_CONTEXT_GET_CLASS (GDK_DRAW_CONTEXT (shared))->begin_frame (GDK_DRAW_CONTEXT (shared), region);
|
||||
return;
|
||||
}
|
||||
|
||||
damage = GDK_GL_CONTEXT_GET_CLASS (context)->get_damage (context);
|
||||
|
||||
if (context->old_updated_area[1])
|
||||
@@ -379,15 +409,6 @@ static void
|
||||
gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *painted)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
|
||||
GdkGLContext *shared;
|
||||
|
||||
shared = gdk_gl_context_get_shared_context (context);
|
||||
if (shared)
|
||||
{
|
||||
GDK_DRAW_CONTEXT_GET_CLASS (GDK_DRAW_CONTEXT (shared))->end_frame (GDK_DRAW_CONTEXT (shared), painted);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -406,6 +427,7 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
|
||||
|
||||
klass->realize = gdk_gl_context_real_realize;
|
||||
klass->get_damage = gdk_gl_context_real_get_damage;
|
||||
klass->is_shared = gdk_gl_context_real_is_shared;
|
||||
|
||||
draw_context_class->begin_frame = gdk_gl_context_real_begin_frame;
|
||||
draw_context_class->end_frame = gdk_gl_context_real_end_frame;
|
||||
@@ -414,7 +436,13 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
|
||||
/**
|
||||
* GdkGLContext:shared-context: (attributes org.gtk.Property.get=gdk_gl_context_get_shared_context)
|
||||
*
|
||||
* The `GdkGLContext` that this context is sharing data with, or %NULL
|
||||
* Always %NULL
|
||||
*
|
||||
* As many contexts can share data now and no single shared context exists
|
||||
* anymore, this function has been deprecated and now always returns %NULL.
|
||||
*
|
||||
* Deprecated: 4.4: Use [method@Gdk.GLContext.is_shared] to check if contexts
|
||||
* can be shared.
|
||||
*/
|
||||
obj_pspecs[PROP_SHARED_CONTEXT] =
|
||||
g_param_spec_object ("shared-context",
|
||||
@@ -423,7 +451,8 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
|
||||
GDK_TYPE_GL_CONTEXT,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_DEPRECATED);
|
||||
|
||||
gobject_class->set_property = gdk_gl_context_set_property;
|
||||
gobject_class->get_property = gdk_gl_context_get_property;
|
||||
@@ -441,6 +470,21 @@ gdk_gl_context_init (GdkGLContext *self)
|
||||
priv->use_es = -1;
|
||||
}
|
||||
|
||||
/* Must have called gdk_display_prepare_gl() before */
|
||||
GdkGLContext *
|
||||
gdk_gl_context_new_for_surface (GdkSurface *surface)
|
||||
{
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GdkGLContext *shared = gdk_display_get_gl_context (display);
|
||||
|
||||
/* assert gdk_display_prepare_gl() had been called */
|
||||
g_assert (shared);
|
||||
|
||||
return g_object_new (G_OBJECT_TYPE (shared),
|
||||
"surface", surface,
|
||||
NULL);
|
||||
}
|
||||
|
||||
GdkGLContextPaintData *
|
||||
gdk_gl_context_get_paint_data (GdkGLContext *context)
|
||||
{
|
||||
@@ -812,6 +856,44 @@ gdk_gl_context_set_is_legacy (GdkGLContext *context,
|
||||
priv->is_legacy = !!is_legacy;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_gl_context_is_shared:
|
||||
* @self: a `GdkGLContext`
|
||||
* @other: the `GdkGLContext` that should be compatible with @self
|
||||
*
|
||||
* Checks if the two GL contexts can share resources.
|
||||
*
|
||||
* When they can, the texture IDs from @other can be used in @self. This
|
||||
* is particularly useful when passing `GdkGLTexture` objects between
|
||||
* different contexts.
|
||||
*
|
||||
* Contexts created for the same display with the same properties will
|
||||
* always be compatible, even if they are created for different surfaces.
|
||||
* For other contexts it depends on the GL backend.
|
||||
*
|
||||
* Both contexts must be realized for this check to succeed. If either one
|
||||
* is not, this function will return %FALSE.
|
||||
*
|
||||
* Returns: %TRUE if the two GL contexts are compatible.
|
||||
*
|
||||
* Since: 4.4
|
||||
*/
|
||||
gboolean
|
||||
gdk_gl_context_is_shared (GdkGLContext *self,
|
||||
GdkGLContext *other)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
|
||||
GdkGLContextPrivate *priv_other = gdk_gl_context_get_instance_private (other);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_GL_CONTEXT (self), FALSE);
|
||||
g_return_val_if_fail (GDK_IS_GL_CONTEXT (other), FALSE);
|
||||
|
||||
if (!priv->realized || !priv_other->realized)
|
||||
return FALSE;
|
||||
|
||||
return GDK_GL_CONTEXT_GET_CLASS (self)->is_shared (self, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_gl_context_set_use_es:
|
||||
* @context: a `GdkGLContext`
|
||||
@@ -1092,12 +1174,16 @@ void
|
||||
gdk_gl_context_make_current (GdkGLContext *context)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
GdkGLContext *current;
|
||||
MaskedContext *current, *masked_context;
|
||||
gboolean surfaceless;
|
||||
|
||||
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
|
||||
|
||||
surfaceless = !gdk_draw_context_is_in_frame (GDK_DRAW_CONTEXT (context));
|
||||
masked_context = mask_context (context, surfaceless);
|
||||
|
||||
current = g_private_get (&thread_current_context);
|
||||
if (current == context)
|
||||
if (current == masked_context)
|
||||
return;
|
||||
|
||||
/* we need to realize the GdkGLContext if it wasn't explicitly realized */
|
||||
@@ -1114,11 +1200,15 @@ gdk_gl_context_make_current (GdkGLContext *context)
|
||||
}
|
||||
}
|
||||
|
||||
if (gdk_display_make_gl_context_current (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)), context))
|
||||
if (!GDK_GL_CONTEXT_GET_CLASS (context)->make_current (context, surfaceless))
|
||||
{
|
||||
g_private_replace (&thread_current_context, g_object_ref (context));
|
||||
gdk_gl_context_check_extensions (context);
|
||||
g_warning ("gdk_gl_context_make_current() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_ref (context);
|
||||
g_private_replace (&thread_current_context, masked_context);
|
||||
gdk_gl_context_check_extensions (context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1157,18 +1247,22 @@ gdk_gl_context_get_surface (GdkGLContext *context)
|
||||
* gdk_gl_context_get_shared_context: (attributes org.gtk.Method.get_property=shared-context)
|
||||
* @context: a `GdkGLContext`
|
||||
*
|
||||
* Retrieves the `GdkGLContext` that this @context share data with.
|
||||
* Used to retrieves the `GdkGLContext` that this @context share data with.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): a `GdkGLContext`
|
||||
* As many contexts can share data now and no single shared context exists
|
||||
* anymore, this function has been deprecated and now always returns %NULL.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): %NULL
|
||||
*
|
||||
* Deprecated: 4.4: Use [method@Gdk.GLContext.is_shared] to check if contexts
|
||||
* can be shared.
|
||||
*/
|
||||
GdkGLContext *
|
||||
gdk_gl_context_get_shared_context (GdkGLContext *context)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL);
|
||||
|
||||
return priv->shared_context;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1208,12 +1302,14 @@ gdk_gl_context_get_version (GdkGLContext *context,
|
||||
void
|
||||
gdk_gl_context_clear_current (void)
|
||||
{
|
||||
GdkGLContext *current;
|
||||
MaskedContext *current;
|
||||
|
||||
current = g_private_get (&thread_current_context);
|
||||
if (current != NULL)
|
||||
{
|
||||
if (gdk_display_make_gl_context_current (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (current)), NULL))
|
||||
GdkGLContext *context = unmask_context (current);
|
||||
|
||||
if (GDK_GL_CONTEXT_GET_CLASS (context)->clear_current (context))
|
||||
g_private_replace (&thread_current_context, NULL);
|
||||
}
|
||||
}
|
||||
@@ -1228,11 +1324,11 @@ gdk_gl_context_clear_current (void)
|
||||
GdkGLContext *
|
||||
gdk_gl_context_get_current (void)
|
||||
{
|
||||
GdkGLContext *current;
|
||||
MaskedContext *current;
|
||||
|
||||
current = g_private_get (&thread_current_context);
|
||||
|
||||
return current;
|
||||
return unmask_context (current);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@@ -45,8 +45,8 @@ GType gdk_gl_context_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay * gdk_gl_context_get_display (GdkGLContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface * gdk_gl_context_get_surface (GdkGLContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface * gdk_gl_context_get_surface (GdkGLContext *context);
|
||||
GDK_DEPRECATED_IN_4_4_FOR(gdk_gl_context_is_shared)
|
||||
GdkGLContext * gdk_gl_context_get_shared_context (GdkGLContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_gl_context_get_version (GdkGLContext *context,
|
||||
@@ -54,6 +54,9 @@ void gdk_gl_context_get_version (GdkGLContext *
|
||||
int *minor);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_gl_context_is_legacy (GdkGLContext *context);
|
||||
GDK_AVAILABLE_IN_4_4
|
||||
gboolean gdk_gl_context_is_shared (GdkGLContext *self,
|
||||
GdkGLContext *other);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_gl_context_set_required_version (GdkGLContext *context,
|
||||
|
@@ -27,6 +27,13 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* Version requirements for EGL contexts.
|
||||
*
|
||||
* If you add support for EGL to your backend, please require this.
|
||||
*/
|
||||
#define GDK_EGL_MIN_VERSION_MAJOR (1)
|
||||
#define GDK_EGL_MIN_VERSION_MINOR (4)
|
||||
|
||||
#define GDK_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_GL_CONTEXT, GdkGLContextClass))
|
||||
#define GDK_IS_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_GL_CONTEXT))
|
||||
#define GDK_GL_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_GL_CONTEXT, GdkGLContextClass))
|
||||
@@ -45,10 +52,16 @@ struct _GdkGLContextClass
|
||||
{
|
||||
GdkDrawContextClass parent_class;
|
||||
|
||||
gboolean (* realize) (GdkGLContext *context,
|
||||
GError **error);
|
||||
gboolean (* realize) (GdkGLContext *context,
|
||||
GError **error);
|
||||
|
||||
cairo_region_t * (* get_damage) (GdkGLContext *context);
|
||||
gboolean (* make_current) (GdkGLContext *context,
|
||||
gboolean surfaceless);
|
||||
gboolean (* clear_current) (GdkGLContext *context);
|
||||
cairo_region_t * (* get_damage) (GdkGLContext *context);
|
||||
|
||||
gboolean (* is_shared) (GdkGLContext *self,
|
||||
GdkGLContext *other);
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@@ -73,6 +86,8 @@ typedef struct {
|
||||
guint use_es : 1;
|
||||
} GdkGLContextPaintData;
|
||||
|
||||
GdkGLContext * gdk_gl_context_new_for_surface (GdkSurface *surface);
|
||||
|
||||
void gdk_gl_context_set_is_legacy (GdkGLContext *context,
|
||||
gboolean is_legacy);
|
||||
|
||||
|
@@ -20,7 +20,8 @@
|
||||
|
||||
#include "gdkgltextureprivate.h"
|
||||
|
||||
#include "gdkcairo.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdktextureprivate.h"
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
@@ -37,7 +38,7 @@ struct _GdkGLTexture {
|
||||
GdkGLContext *context;
|
||||
guint id;
|
||||
|
||||
cairo_surface_t *saved;
|
||||
GdkTexture *saved;
|
||||
|
||||
GDestroyNotify destroy;
|
||||
gpointer data;
|
||||
@@ -64,50 +65,258 @@ gdk_gl_texture_dispose (GObject *object)
|
||||
g_clear_object (&self->context);
|
||||
self->id = 0;
|
||||
|
||||
if (self->saved)
|
||||
{
|
||||
cairo_surface_destroy (self->saved);
|
||||
self->saved = NULL;
|
||||
}
|
||||
g_clear_object (&self->saved);
|
||||
|
||||
G_OBJECT_CLASS (gdk_gl_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_download (GdkTexture *texture,
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
typedef struct _InvokeData
|
||||
{
|
||||
GdkGLTexture *self = GDK_GL_TEXTURE (texture);
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
GdkGLTexture *self;
|
||||
volatile int spinlock;
|
||||
GFunc func;
|
||||
gpointer data;
|
||||
} InvokeData;
|
||||
|
||||
surface = cairo_image_surface_create_for_data (data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
area->width, area->height,
|
||||
stride);
|
||||
static gboolean
|
||||
gdk_gl_texture_invoke_callback (gpointer data)
|
||||
{
|
||||
InvokeData *invoke = data;
|
||||
GdkGLContext *context;
|
||||
|
||||
cr = cairo_create (surface);
|
||||
context = gdk_display_get_gl_context (gdk_gl_context_get_display (invoke->self->context));
|
||||
|
||||
if (self->saved)
|
||||
gdk_gl_context_make_current (context);
|
||||
glBindTexture (GL_TEXTURE_2D, invoke->self->id);
|
||||
|
||||
invoke->func (invoke->self, invoke->data);
|
||||
|
||||
g_atomic_int_set (&invoke->spinlock, 1);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_run (GdkGLTexture *self,
|
||||
GFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
InvokeData invoke = { self, 0, func, data };
|
||||
|
||||
g_main_context_invoke (NULL, gdk_gl_texture_invoke_callback, &invoke);
|
||||
|
||||
while (g_atomic_int_get (&invoke.spinlock) == 0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gdk_gl_texture_get_tex_image (GdkGLTexture *self,
|
||||
GLenum gl_format,
|
||||
GLenum gl_type,
|
||||
GLvoid *data)
|
||||
{
|
||||
if (gdk_gl_context_get_use_es (self->context))
|
||||
{
|
||||
cairo_set_source_surface (cr, self->saved, 0, 0);
|
||||
cairo_paint (cr);
|
||||
GdkTexture *texture = GDK_TEXTURE (self);
|
||||
GLuint fbo;
|
||||
|
||||
glGenFramebuffers (1, &fbo);
|
||||
glBindFramebuffer (GL_FRAMEBUFFER, fbo);
|
||||
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->id, 0);
|
||||
glReadPixels (0, 0,
|
||||
texture->width, texture->height,
|
||||
gl_format,
|
||||
gl_type,
|
||||
data);
|
||||
glBindFramebuffer (GL_FRAMEBUFFER, 0);
|
||||
glDeleteFramebuffers (1, &fbo);
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkSurface *gl_surface;
|
||||
glGetTexImage (GL_TEXTURE_2D,
|
||||
0,
|
||||
gl_format,
|
||||
gl_type,
|
||||
data);
|
||||
}
|
||||
}
|
||||
static void
|
||||
gdk_gl_texture_do_download_texture (gpointer texture_,
|
||||
gpointer result_)
|
||||
{
|
||||
GdkTexture *texture = texture_;
|
||||
GdkTexture **result = result_;
|
||||
GdkMemoryFormat format;
|
||||
GLint internal_format, gl_format, gl_type;
|
||||
guchar *data;
|
||||
gsize stride;
|
||||
GBytes *bytes;
|
||||
|
||||
gl_surface = gdk_gl_context_get_surface (self->context);
|
||||
gdk_cairo_draw_from_gl (cr, gl_surface, self->id, GL_TEXTURE, 1,
|
||||
area->x, area->y,
|
||||
area->width, area->height);
|
||||
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format);
|
||||
|
||||
switch (internal_format)
|
||||
{
|
||||
case GL_RGB8:
|
||||
format = GDK_MEMORY_R8G8B8;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case GL_RGBA8:
|
||||
format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case GL_RGB16:
|
||||
format = GDK_MEMORY_R16G16B16;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
|
||||
case GL_RGBA16:
|
||||
format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
|
||||
case GL_RGB16F:
|
||||
format = GDK_MEMORY_R16G16B16_FLOAT;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_HALF_FLOAT;
|
||||
break;
|
||||
|
||||
case GL_RGBA16F:
|
||||
format = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_HALF_FLOAT;
|
||||
break;
|
||||
|
||||
case GL_RGB32F:
|
||||
format = GDK_MEMORY_R32G32B32_FLOAT;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_FLOAT;
|
||||
break;
|
||||
|
||||
case GL_RGBA32F:
|
||||
format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_FLOAT;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warning ("Texture in unexpected format 0x%X (%d). File a bug about adding it to GTK", internal_format, internal_format);
|
||||
/* fallback to the dumbest possible format
|
||||
* so that even age old GLES can do it */
|
||||
format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
}
|
||||
|
||||
stride = gdk_memory_format_bytes_per_pixel (format) * texture->width;
|
||||
data = g_malloc (stride * texture->height);
|
||||
|
||||
gdk_gl_texture_get_tex_image (texture_,
|
||||
gl_format,
|
||||
gl_type,
|
||||
data);
|
||||
|
||||
bytes = g_bytes_new_take (data, stride * texture->height);
|
||||
*result = gdk_memory_texture_new (texture->width,
|
||||
texture->height,
|
||||
format,
|
||||
bytes,
|
||||
stride);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
gdk_gl_texture_download_texture (GdkTexture *texture)
|
||||
{
|
||||
GdkGLTexture *self = GDK_GL_TEXTURE (texture);
|
||||
GdkTexture *result;
|
||||
|
||||
if (self->saved)
|
||||
return g_object_ref (self->saved);
|
||||
|
||||
gdk_gl_texture_run (self, gdk_gl_texture_do_download_texture, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_do_download (gpointer texture,
|
||||
gpointer data)
|
||||
{
|
||||
glGetTexImage (GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_BGRA,
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
GL_UNSIGNED_BYTE,
|
||||
#else
|
||||
#error "Unknown byte order for gdk_gl_texture_download()"
|
||||
#endif
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_download (GdkTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkGLTexture *self = GDK_GL_TEXTURE (texture);
|
||||
|
||||
if (self->saved)
|
||||
{
|
||||
gdk_texture_download (self->saved, data, stride);
|
||||
return;
|
||||
}
|
||||
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_finish (surface);
|
||||
cairo_surface_destroy (surface);
|
||||
if (gdk_gl_context_get_use_es (self->context) ||
|
||||
stride != texture->width * 4)
|
||||
{
|
||||
GDK_TEXTURE_CLASS (gdk_gl_texture_parent_class)->download (texture, data, stride);
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_gl_texture_run (self, gdk_gl_texture_do_download, data);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_do_download_float (gpointer texture,
|
||||
gpointer data)
|
||||
{
|
||||
glGetTexImage (GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGBA,
|
||||
GL_FLOAT,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_download_float (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkGLTexture *self = GDK_GL_TEXTURE (texture);
|
||||
|
||||
if (self->saved)
|
||||
{
|
||||
gdk_texture_download_float (self->saved, data, stride);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gdk_gl_context_get_use_es (self->context) ||
|
||||
stride != texture->width * 4)
|
||||
{
|
||||
GDK_TEXTURE_CLASS (gdk_gl_texture_parent_class)->download_float (texture, data, stride);
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_gl_texture_run (self, gdk_gl_texture_do_download_float, data);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -116,7 +325,9 @@ gdk_gl_texture_class_init (GdkGLTextureClass *klass)
|
||||
GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
texture_class->download_texture = gdk_gl_texture_download_texture;
|
||||
texture_class->download = gdk_gl_texture_download;
|
||||
texture_class->download_float = gdk_gl_texture_download_float;
|
||||
gobject_class->dispose = gdk_gl_texture_dispose;
|
||||
}
|
||||
|
||||
@@ -150,24 +361,10 @@ gdk_gl_texture_get_id (GdkGLTexture *self)
|
||||
void
|
||||
gdk_gl_texture_release (GdkGLTexture *self)
|
||||
{
|
||||
GdkSurface *surface;
|
||||
GdkTexture *texture;
|
||||
cairo_t *cr;
|
||||
|
||||
g_return_if_fail (GDK_IS_GL_TEXTURE (self));
|
||||
g_return_if_fail (self->saved == NULL);
|
||||
|
||||
texture = GDK_TEXTURE (self);
|
||||
self->saved = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
texture->width, texture->height);
|
||||
|
||||
cr = cairo_create (self->saved);
|
||||
|
||||
surface = gdk_gl_context_get_surface (self->context);
|
||||
gdk_cairo_draw_from_gl (cr, surface, self->id, GL_TEXTURE, 1, 0, 0,
|
||||
texture->width, texture->height);
|
||||
|
||||
cairo_destroy (cr);
|
||||
self->saved = gdk_texture_download_texture (GDK_TEXTURE (self));
|
||||
|
||||
if (self->destroy)
|
||||
{
|
||||
|
@@ -17,12 +17,12 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkhslaprivate.h"
|
||||
#include "gdkhslaprivate.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
void
|
||||
_gtk_hsla_init_from_rgba (GtkHSLA *hsla,
|
||||
_gdk_hsla_init_from_rgba (GdkHSLA *hsla,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
float min;
|
||||
@@ -31,21 +31,21 @@ _gtk_hsla_init_from_rgba (GtkHSLA *hsla,
|
||||
float green;
|
||||
float blue;
|
||||
float delta;
|
||||
|
||||
|
||||
g_return_if_fail (hsla != NULL);
|
||||
g_return_if_fail (rgba != NULL);
|
||||
|
||||
red = rgba->red;
|
||||
green = rgba->green;
|
||||
blue = rgba->blue;
|
||||
|
||||
|
||||
if (red > green)
|
||||
{
|
||||
if (red > blue)
|
||||
max = red;
|
||||
else
|
||||
max = blue;
|
||||
|
||||
|
||||
if (green < blue)
|
||||
min = green;
|
||||
else
|
||||
@@ -57,25 +57,25 @@ _gtk_hsla_init_from_rgba (GtkHSLA *hsla,
|
||||
max = green;
|
||||
else
|
||||
max = blue;
|
||||
|
||||
|
||||
if (red < blue)
|
||||
min = red;
|
||||
else
|
||||
min = blue;
|
||||
}
|
||||
|
||||
|
||||
hsla->lightness = (max + min) / 2;
|
||||
hsla->saturation = 0;
|
||||
hsla->hue = 0;
|
||||
hsla->alpha = rgba->alpha;
|
||||
|
||||
|
||||
if (max != min)
|
||||
{
|
||||
if (hsla->lightness <= 0.5)
|
||||
hsla->saturation = (max - min) / (max + min);
|
||||
else
|
||||
hsla->saturation = (max - min) / (2 - max - min);
|
||||
|
||||
|
||||
delta = max -min;
|
||||
if (red == max)
|
||||
hsla->hue = (green - blue) / delta;
|
||||
@@ -83,7 +83,7 @@ _gtk_hsla_init_from_rgba (GtkHSLA *hsla,
|
||||
hsla->hue = 2 + (blue - red) / delta;
|
||||
else if (blue == max)
|
||||
hsla->hue = 4 + (red - green) / delta;
|
||||
|
||||
|
||||
hsla->hue *= 60;
|
||||
if (hsla->hue < 0.0)
|
||||
hsla->hue += 360;
|
||||
@@ -92,22 +92,22 @@ _gtk_hsla_init_from_rgba (GtkHSLA *hsla,
|
||||
|
||||
void
|
||||
_gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
const GtkHSLA *hsla)
|
||||
const GdkHSLA *hsla)
|
||||
{
|
||||
float hue;
|
||||
float lightness;
|
||||
float saturation;
|
||||
float m1, m2;
|
||||
|
||||
|
||||
lightness = hsla->lightness;
|
||||
saturation = hsla->saturation;
|
||||
|
||||
|
||||
if (lightness <= 0.5)
|
||||
m2 = lightness * (1 + saturation);
|
||||
else
|
||||
m2 = lightness + saturation - lightness * saturation;
|
||||
m1 = 2 * lightness - m2;
|
||||
|
||||
|
||||
rgba->alpha = hsla->alpha;
|
||||
|
||||
if (saturation == 0)
|
||||
@@ -123,7 +123,7 @@ _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
hue -= 360;
|
||||
while (hue < 0)
|
||||
hue += 360;
|
||||
|
||||
|
||||
if (hue < 60)
|
||||
rgba->red = m1 + (m2 - m1) * hue / 60;
|
||||
else if (hue < 180)
|
||||
@@ -132,13 +132,13 @@ _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
rgba->red = m1 + (m2 - m1) * (240 - hue) / 60;
|
||||
else
|
||||
rgba->red = m1;
|
||||
|
||||
|
||||
hue = hsla->hue;
|
||||
while (hue > 360)
|
||||
hue -= 360;
|
||||
while (hue < 0)
|
||||
hue += 360;
|
||||
|
||||
|
||||
if (hue < 60)
|
||||
rgba->green = m1 + (m2 - m1) * hue / 60;
|
||||
else if (hue < 180)
|
||||
@@ -147,13 +147,13 @@ _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
rgba->green = m1 + (m2 - m1) * (240 - hue) / 60;
|
||||
else
|
||||
rgba->green = m1;
|
||||
|
||||
|
||||
hue = hsla->hue - 120;
|
||||
while (hue > 360)
|
||||
hue -= 360;
|
||||
while (hue < 0)
|
||||
hue += 360;
|
||||
|
||||
|
||||
if (hue < 60)
|
||||
rgba->blue = m1 + (m2 - m1) * hue / 60;
|
||||
else if (hue < 180)
|
||||
@@ -166,8 +166,8 @@ _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_hsla_shade (GtkHSLA *dest,
|
||||
const GtkHSLA *src,
|
||||
_gdk_hsla_shade (GdkHSLA *dest,
|
||||
const GdkHSLA *src,
|
||||
float factor)
|
||||
{
|
||||
g_return_if_fail (dest != NULL);
|
@@ -22,23 +22,23 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkHSLA GtkHSLA;
|
||||
typedef struct _GdkHSLA GdkHSLA;
|
||||
|
||||
struct _GtkHSLA {
|
||||
struct _GdkHSLA {
|
||||
float hue;
|
||||
float saturation;
|
||||
float lightness;
|
||||
float alpha;
|
||||
};
|
||||
|
||||
void _gtk_hsla_init_from_rgba (GtkHSLA *hsla,
|
||||
void _gdk_hsla_init_from_rgba (GdkHSLA *hsla,
|
||||
const GdkRGBA *rgba);
|
||||
/* Yes, I can name that function like this! */
|
||||
void _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
const GtkHSLA *hsla);
|
||||
const GdkHSLA *hsla);
|
||||
|
||||
void _gtk_hsla_shade (GtkHSLA *dest,
|
||||
const GtkHSLA *src,
|
||||
void _gdk_hsla_shade (GdkHSLA *dest,
|
||||
const GdkHSLA *src,
|
||||
float factor);
|
||||
|
||||
G_END_DECLS
|
@@ -20,6 +20,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gsk/ngl/fp16private.h"
|
||||
|
||||
/**
|
||||
* GdkMemoryTexture:
|
||||
@@ -49,6 +50,10 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
return 3;
|
||||
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
@@ -58,9 +63,19 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
return 4;
|
||||
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
return 3;
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
return 6;
|
||||
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
return 8;
|
||||
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
return 12;
|
||||
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
return 16;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
@@ -69,6 +84,41 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
|
||||
}
|
||||
}
|
||||
|
||||
static gsize
|
||||
gdk_memory_format_alignment (GdkMemoryFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
return G_ALIGNOF (guchar);
|
||||
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
return G_ALIGNOF (guint16);
|
||||
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
return G_ALIGNOF (guint16);
|
||||
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
return G_ALIGNOF (float);
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return G_ALIGNOF (double);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_memory_texture_dispose (GObject *object)
|
||||
{
|
||||
@@ -79,22 +129,41 @@ gdk_memory_texture_dispose (GObject *object)
|
||||
G_OBJECT_CLASS (gdk_memory_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
gdk_memory_texture_download_texture (GdkTexture *texture)
|
||||
{
|
||||
return g_object_ref (texture);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_memory_texture_download (GdkTexture *texture,
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
gdk_memory_texture_download (GdkTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture);
|
||||
|
||||
gdk_memory_convert (data, stride,
|
||||
GDK_MEMORY_CAIRO_FORMAT_ARGB32,
|
||||
(guchar *) g_bytes_get_data (self->bytes, NULL)
|
||||
+ area->x * gdk_memory_format_bytes_per_pixel (self->format)
|
||||
+ area->y * self->stride,
|
||||
GDK_MEMORY_CONVERT_DOWNLOAD,
|
||||
(guchar *) g_bytes_get_data (self->bytes, NULL),
|
||||
self->stride,
|
||||
self->format,
|
||||
area->width, area->height);
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_memory_texture_download_float (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture);
|
||||
|
||||
gdk_memory_convert_to_float (data, stride,
|
||||
(guchar *) g_bytes_get_data (self->bytes, NULL),
|
||||
self->stride,
|
||||
self->format,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -103,7 +172,9 @@ gdk_memory_texture_class_init (GdkMemoryTextureClass *klass)
|
||||
GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
texture_class->download_texture = gdk_memory_texture_download_texture;
|
||||
texture_class->download = gdk_memory_texture_download;
|
||||
texture_class->download_float = gdk_memory_texture_download_float;
|
||||
gobject_class->dispose = gdk_memory_texture_dispose;
|
||||
}
|
||||
|
||||
@@ -112,6 +183,41 @@ gdk_memory_texture_init (GdkMemoryTexture *self)
|
||||
{
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
gdk_memory_sanitize (GBytes *bytes,
|
||||
int width,
|
||||
int height,
|
||||
GdkMemoryFormat format,
|
||||
gsize stride,
|
||||
gsize *out_stride)
|
||||
{
|
||||
gsize align, size, copy_stride, bpp;
|
||||
const guchar *data;
|
||||
guchar *copy;
|
||||
int y;
|
||||
|
||||
data = g_bytes_get_data (bytes, &size);
|
||||
align = gdk_memory_format_alignment (format);
|
||||
|
||||
if (GPOINTER_TO_SIZE (data) % align == 0 &&
|
||||
stride % align == 0)
|
||||
{
|
||||
*out_stride = stride;
|
||||
return g_bytes_ref (bytes);
|
||||
}
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (format);
|
||||
copy_stride = bpp * width;
|
||||
/* align to multiples of 4, just to be sure */
|
||||
copy_stride = (copy_stride + 3) & ~3;
|
||||
copy = g_malloc (copy_stride * height);
|
||||
for (y = 0; y < height; y++)
|
||||
memcpy (copy + y * copy_stride, data + y * stride, bpp * width);
|
||||
|
||||
*out_stride = copy_stride;
|
||||
return g_bytes_new_take (copy, copy_stride * height);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_new:
|
||||
* @width: the width of the texture
|
||||
@@ -136,13 +242,20 @@ gdk_memory_texture_new (int width,
|
||||
{
|
||||
GdkMemoryTexture *self;
|
||||
|
||||
g_return_val_if_fail (width > 0, NULL);
|
||||
g_return_val_if_fail (height > 0, NULL);
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
g_return_val_if_fail (stride >= width * gdk_memory_format_bytes_per_pixel (format), NULL);
|
||||
|
||||
bytes = gdk_memory_sanitize (bytes, width, height, format, stride, &stride);
|
||||
|
||||
self = g_object_new (GDK_TYPE_MEMORY_TEXTURE,
|
||||
"width", width,
|
||||
"height", height,
|
||||
NULL);
|
||||
|
||||
self->format = format;
|
||||
self->bytes = g_bytes_ref (bytes);
|
||||
self->bytes = bytes;
|
||||
self->stride = stride;
|
||||
|
||||
return GDK_TEXTURE (self);
|
||||
@@ -283,6 +396,109 @@ SWIZZLE_PREMULTIPLY (3,0,1,2, 0,1,2,3)
|
||||
SWIZZLE_PREMULTIPLY (3,0,1,2, 3,0,1,2)
|
||||
SWIZZLE_PREMULTIPLY (3,0,1,2, 0,3,2,1)
|
||||
|
||||
#define CONVERT_FUNC(name,suffix,R,G,B,A,step) \
|
||||
static void \
|
||||
convert_ ## name ## _to_ ## suffix (guchar *dest_data, \
|
||||
gsize dest_stride, \
|
||||
const guchar *src_data, \
|
||||
gsize src_stride, \
|
||||
gsize width, \
|
||||
gsize height) \
|
||||
{ \
|
||||
gsize x, y; \
|
||||
\
|
||||
for (y = 0; y < height; y++) \
|
||||
{ \
|
||||
for (x = 0; x < width; x++) \
|
||||
{ \
|
||||
guchar conv[4]; \
|
||||
convert_pixel_ ## name (conv, src_data + step * x); \
|
||||
dest_data[4 * x + R] = conv[0]; \
|
||||
dest_data[4 * x + G] = conv[1]; \
|
||||
dest_data[4 * x + B] = conv[2]; \
|
||||
dest_data[4 * x + A] = conv[3]; \
|
||||
} \
|
||||
\
|
||||
dest_data += dest_stride; \
|
||||
src_data += src_stride; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CONVERT_FUNCS(name,step) \
|
||||
CONVERT_FUNC(name, download_le, 2, 1, 0, 3, step) \
|
||||
CONVERT_FUNC(name, download_be, 1, 2, 3, 0, step) \
|
||||
CONVERT_FUNC(name, gles_rgba, 0, 1, 2, 3, step) \
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgb16 (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
const guint16 *src = (const guint16 *) src_data;
|
||||
dest_data[0] = (guchar)(src[0] >> 8);
|
||||
dest_data[1] = (guchar)(src[1] >> 8);
|
||||
dest_data[2] = (guchar)(src[2] >> 8);
|
||||
dest_data[3] = 0xFF;
|
||||
}
|
||||
CONVERT_FUNCS(rgb16, 3 * sizeof (guint16))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgba16 (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
const guint16 *src = (const guint16 *) src_data;
|
||||
dest_data[0] = (guchar)(src[0] >> 8);
|
||||
dest_data[1] = (guchar)(src[1] >> 8);
|
||||
dest_data[2] = (guchar)(src[2] >> 8);
|
||||
dest_data[3] = (guchar)(src[3] >> 8);
|
||||
}
|
||||
CONVERT_FUNCS(rgba16, 4 * sizeof (guint16))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgb16f (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
float src[4];
|
||||
guint16 tmp[4];
|
||||
memcpy(tmp, src_data, sizeof(guint16) * 3);
|
||||
half_to_float4(tmp, src);
|
||||
dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
|
||||
dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
|
||||
dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
|
||||
dest_data[3] = 0xFF;
|
||||
}
|
||||
CONVERT_FUNCS(rgb16f, 3 * sizeof (guint16))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgba16f (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
float src[4];
|
||||
half_to_float4((const guint16 *) src_data, src);
|
||||
dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
|
||||
dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
|
||||
dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
|
||||
dest_data[3] = CLAMP (src[3] * 256.f, 0.f, 255.f);
|
||||
}
|
||||
CONVERT_FUNCS(rgba16f, 4 * sizeof (guint16))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgb32f (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
float *src = (float *) src_data;
|
||||
dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
|
||||
dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
|
||||
dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
|
||||
dest_data[3] = 0xFF;
|
||||
}
|
||||
CONVERT_FUNCS(rgb32f, 3 * sizeof (float))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgba32f (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
float *src = (float *) src_data;
|
||||
dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
|
||||
dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
|
||||
dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
|
||||
dest_data[3] = CLAMP (src[3] * 256.f, 0.f, 255.f);
|
||||
}
|
||||
CONVERT_FUNCS(rgba32f, 4 * sizeof (float))
|
||||
|
||||
typedef void (* ConversionFunc) (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
const guchar *src_data,
|
||||
@@ -290,7 +506,7 @@ typedef void (* ConversionFunc) (guchar *dest_data,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
static ConversionFunc converters[GDK_MEMORY_N_FORMATS][3] =
|
||||
static ConversionFunc converters[GDK_MEMORY_N_FORMATS][GDK_MEMORY_N_CONVERSIONS] =
|
||||
{
|
||||
{ convert_memcpy, convert_swizzle3210, convert_swizzle2103 },
|
||||
{ convert_swizzle3210, convert_memcpy, convert_swizzle3012 },
|
||||
@@ -300,21 +516,192 @@ static ConversionFunc converters[GDK_MEMORY_N_FORMATS][3] =
|
||||
{ convert_swizzle_premultiply_3210_3012, convert_swizzle_premultiply_0123_3012, convert_swizzle_premultiply_3012_3012 },
|
||||
{ convert_swizzle_premultiply_3210_0321, convert_swizzle_premultiply_0123_0321, convert_swizzle_premultiply_3012_0321 },
|
||||
{ convert_swizzle_opaque_3210, convert_swizzle_opaque_0123, convert_swizzle_opaque_3012 },
|
||||
{ convert_swizzle_opaque_3012, convert_swizzle_opaque_0321, convert_swizzle_opaque_3210 }
|
||||
{ convert_swizzle_opaque_3012, convert_swizzle_opaque_0321, convert_swizzle_opaque_3210 },
|
||||
{ convert_rgb16_to_download_le, convert_rgb16_to_download_be, convert_rgb16_to_gles_rgba },
|
||||
{ convert_rgba16_to_download_le, convert_rgba16_to_download_be, convert_rgba16_to_gles_rgba },
|
||||
{ convert_rgb16f_to_download_le, convert_rgb16f_to_download_be, convert_rgb16f_to_gles_rgba },
|
||||
{ convert_rgba16f_to_download_le, convert_rgba16f_to_download_be, convert_rgba16f_to_gles_rgba },
|
||||
{ convert_rgb32f_to_download_le, convert_rgb32f_to_download_be, convert_rgb32f_to_gles_rgba },
|
||||
{ convert_rgba32f_to_download_le, convert_rgba32f_to_download_be, convert_rgba32f_to_gles_rgba }
|
||||
};
|
||||
|
||||
void
|
||||
gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryFormat dest_format,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height)
|
||||
gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryConversion dest_format,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
g_assert (dest_format < 3);
|
||||
g_assert (src_format < GDK_MEMORY_N_FORMATS);
|
||||
|
||||
converters[src_format][dest_format] (dest_data, dest_stride, src_data, src_stride, width, height);
|
||||
}
|
||||
|
||||
#define CONVERT_FLOAT(R,G,B,A,premultiply) G_STMT_START {\
|
||||
for (y = 0; y < height; y++) \
|
||||
{ \
|
||||
for (x = 0; x < width; x++) \
|
||||
{ \
|
||||
if (A >= 0) \
|
||||
{ \
|
||||
dest_data[4 * x + 0] = src_data[4 * x + R] / 255.0f; \
|
||||
dest_data[4 * x + 1] = src_data[4 * x + G] / 255.0f; \
|
||||
dest_data[4 * x + 2] = src_data[4 * x + B] / 255.0f; \
|
||||
dest_data[4 * x + 3] = src_data[4 * x + A] / 255.0f; \
|
||||
if (premultiply) \
|
||||
{ \
|
||||
dest_data[4 * x + 0] *= dest_data[4 * x + 3]; \
|
||||
dest_data[4 * x + 1] *= dest_data[4 * x + 3]; \
|
||||
dest_data[4 * x + 2] *= dest_data[4 * x + 3]; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
dest_data[4 * x + 0] = src_data[3 * x + R] / 255.0f; \
|
||||
dest_data[4 * x + 1] = src_data[3 * x + G] / 255.0f; \
|
||||
dest_data[4 * x + 2] = src_data[3 * x + B] / 255.0f; \
|
||||
dest_data[4 * x + 3] = 1.0; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
dest_data += dest_stride; \
|
||||
src_data += src_stride; \
|
||||
} \
|
||||
}G_STMT_END
|
||||
|
||||
#define CONVERT_FLOAT_PIXEL(func,step) G_STMT_START{\
|
||||
for (y = 0; y < height; y++) \
|
||||
{ \
|
||||
for (x = 0; x < width; x++) \
|
||||
{ \
|
||||
func (dest_data + 4 * x, src_data + step * x); \
|
||||
} \
|
||||
\
|
||||
dest_data += dest_stride; \
|
||||
src_data += src_stride; \
|
||||
} \
|
||||
}G_STMT_END
|
||||
|
||||
static inline void
|
||||
convert_rgb16_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
const guint16 *src = (const guint16 *) src_data;
|
||||
dest[0] = src[0] / 65535.f;
|
||||
dest[1] = src[1] / 65535.f;
|
||||
dest[2] = src[2] / 65535.f;
|
||||
dest[3] = 1.0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgba16_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
const guint16 *src = (const guint16 *) src_data;
|
||||
dest[0] = src[0] / 65535.f;
|
||||
dest[1] = src[1] / 65535.f;
|
||||
dest[2] = src[2] / 65535.f;
|
||||
dest[3] = src[3] / 65535.f;
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgb16f_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
guint16 tmp[4];
|
||||
memcpy(tmp, src_data, sizeof(guint16) * 3);
|
||||
tmp[3] = FP16_ONE;
|
||||
half_to_float4 (tmp, dest);
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgba16f_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
half_to_float4 ((const guint16 *) src_data, dest);
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgb32f_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
const float *src = (const float *) src_data;
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
dest[3] = 1.0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgba32f_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
const float *src = (const float *) src_data;
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
dest[3] = src[3];
|
||||
}
|
||||
|
||||
void
|
||||
gdk_memory_convert_to_float (float *dest_data,
|
||||
gsize dest_stride,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
gsize x, y;
|
||||
|
||||
switch (src_format)
|
||||
{
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
CONVERT_FLOAT (2, 1, 0, 3, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
CONVERT_FLOAT (1, 2, 3, 0, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
CONVERT_FLOAT (0, 1, 2, 3, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
CONVERT_FLOAT (2, 1, 0, 3, TRUE);
|
||||
break;
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
CONVERT_FLOAT (1, 2, 3, 0, TRUE);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
CONVERT_FLOAT (0, 1, 2, 3, TRUE);
|
||||
break;
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
CONVERT_FLOAT (3, 2, 1, 0, TRUE);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
CONVERT_FLOAT (0, 1, 2, -1, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
CONVERT_FLOAT (2, 1, 0, -1, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgb16_to_float, 3 * sizeof (guint16));
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgba16_to_float, 4 * sizeof (guint16));
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgb16f_to_float, 3 * sizeof (guint16));
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgba16f_to_float, 4 * sizeof (guint16));
|
||||
break;
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgb32f_to_float, 3 * sizeof (float));
|
||||
break;
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgba32f_to_float, 4 * sizeof (float));
|
||||
break;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
@@ -42,6 +42,20 @@ G_BEGIN_DECLS
|
||||
* @GDK_MEMORY_A8B8G8R8: 4 bytes; for alpha, blue, green, red.
|
||||
* @GDK_MEMORY_R8G8B8: 3 bytes; for red, green, blue. The data is opaque.
|
||||
* @GDK_MEMORY_B8G8R8: 3 bytes; for blue, green, red. The data is opaque.
|
||||
* @GDK_MEMORY_R16G16B16: 3 guint16 values; for red, green, blue. Since 4.6
|
||||
* @GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: 4 guint16 values; for red, green,
|
||||
* blue, alpha. The color values are premultiplied with the alpha value.
|
||||
* Since 4.6
|
||||
* @GDK_MEMORY_R16G16B16_FLOAT: 3 half-float values; for red, green, blue.
|
||||
* The data is opaque. Since 4.6
|
||||
* @GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: 4 half-float values; for
|
||||
* red, green, blue and alpha. The color values are premultiplied with
|
||||
* the alpha value. Since 4.6
|
||||
* @GDK_MEMORY_B32G32R32_FLOAT: 3 float values; for blue, green, red.
|
||||
* The data is opaque. Since 4.6
|
||||
* @GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: 4 float values; for
|
||||
* red, green, blue and alpha. The color values are premultiplied with
|
||||
* the alpha value. Since 4.6
|
||||
* @GDK_MEMORY_N_FORMATS: The number of formats. This value will change as
|
||||
* more formats get added, so do not rely on its concrete integer.
|
||||
*
|
||||
@@ -67,6 +81,12 @@ typedef enum {
|
||||
GDK_MEMORY_A8B8G8R8,
|
||||
GDK_MEMORY_R8G8B8,
|
||||
GDK_MEMORY_B8G8R8,
|
||||
GDK_MEMORY_R16G16B16,
|
||||
GDK_MEMORY_R16G16B16A16_PREMULTIPLIED,
|
||||
GDK_MEMORY_R16G16B16_FLOAT,
|
||||
GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED,
|
||||
GDK_MEMORY_R32G32B32_FLOAT,
|
||||
GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED,
|
||||
|
||||
GDK_MEMORY_N_FORMATS
|
||||
} GdkMemoryFormat;
|
||||
|
@@ -29,7 +29,21 @@ G_BEGIN_DECLS
|
||||
#define GDK_MEMORY_GDK_PIXBUF_OPAQUE GDK_MEMORY_R8G8B8
|
||||
#define GDK_MEMORY_GDK_PIXBUF_ALPHA GDK_MEMORY_R8G8B8A8
|
||||
|
||||
#define GDK_MEMORY_CAIRO_FORMAT_ARGB32 GDK_MEMORY_DEFAULT
|
||||
typedef enum {
|
||||
GDK_MEMORY_CONVERT_DOWNLOAD_LITTLE_ENDIAN,
|
||||
GDK_MEMORY_CONVERT_DOWNLOAD_BIT_ENDIAN,
|
||||
GDK_MEMORY_CONVERT_GLES_RGBA,
|
||||
|
||||
GDK_MEMORY_N_CONVERSIONS
|
||||
} GdkMemoryConversion;
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
#define GDK_MEMORY_CONVERT_DOWNLOAD GDK_MEMORY_CONVERT_DOWNLOAD_LITTLE_ENDIAN
|
||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
#define GDK_MEMORY_CONVERT_DOWNLOAD GDK_MEMORY_CONVERT_DOWNLOAD_BIG_ENDIAN
|
||||
#else
|
||||
#error "Unknown byte order for GDK_MEMORY_CONVERT_DOWNLOAD"
|
||||
#endif
|
||||
|
||||
gsize gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format);
|
||||
|
||||
@@ -37,14 +51,22 @@ GdkMemoryFormat gdk_memory_texture_get_format (GdkMemoryTexture *
|
||||
const guchar * gdk_memory_texture_get_data (GdkMemoryTexture *self);
|
||||
gsize gdk_memory_texture_get_stride (GdkMemoryTexture *self);
|
||||
|
||||
void gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryFormat dest_format,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height);
|
||||
void gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryConversion dest_format,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
void gdk_memory_convert_to_float (float *dest_data,
|
||||
gsize dest_stride,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -70,17 +70,17 @@ typedef enum {
|
||||
* snapshot at or 0 if none. This is purely a hint. The object must still
|
||||
* be able to render at any size.
|
||||
* @get_intrinsic_aspect_ratio: The preferred aspect ratio for this object
|
||||
* or 0 if none. If both [vfunc@Gdk.PaintableInterface.get_intrinsic_width]
|
||||
* and [vfunc@Gdk.PaintableInterface.get_intrinsic_height] return non-zero
|
||||
* or 0 if none. If both [vfunc@Gdk.Paintable.get_intrinsic_width]
|
||||
* and [vfunc@Gdk.Paintable.get_intrinsic_height] return non-zero
|
||||
* values, this function should return the aspect ratio computed from those.
|
||||
*
|
||||
* The list of functions that can be implemented for the `GdkPaintable`
|
||||
* interface.
|
||||
*
|
||||
* Note that apart from the [vfunc@Gdk.PaintableInterface.snapshot] function,
|
||||
* Note that apart from the [vfunc@Gdk.Paintable.snapshot] function,
|
||||
* no virtual function of this interface is mandatory to implement, though it
|
||||
* is a good idea to implement [vfunc@Gdk.PaintableInterface.get_current_image]
|
||||
* for non-static paintables and [vfunc@Gdk.PaintableInterface.get_flags] if the
|
||||
* is a good idea to implement [vfunc@Gdk.Paintable.get_current_image]
|
||||
* for non-static paintables and [vfunc@Gdk.Paintable.get_flags] if the
|
||||
* image is not dynamic as the default implementation returns no flags and
|
||||
* that will make the implementation likely quite slow.
|
||||
*/
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "gdkhslaprivate.h"
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GdkRGBA, gdk_rgba,
|
||||
gdk_rgba_copy, gdk_rgba_free)
|
||||
@@ -186,6 +187,7 @@ gdk_rgba_parse (GdkRGBA *rgba,
|
||||
const char *spec)
|
||||
{
|
||||
gboolean has_alpha;
|
||||
gboolean is_hsl;
|
||||
double r, g, b, a;
|
||||
char *str = (char *) spec;
|
||||
char *p;
|
||||
@@ -196,11 +198,26 @@ gdk_rgba_parse (GdkRGBA *rgba,
|
||||
if (strncmp (str, "rgba", 4) == 0)
|
||||
{
|
||||
has_alpha = TRUE;
|
||||
is_hsl = FALSE;
|
||||
str += 4;
|
||||
}
|
||||
else if (strncmp (str, "rgb", 3) == 0)
|
||||
{
|
||||
has_alpha = FALSE;
|
||||
is_hsl = FALSE;
|
||||
a = 1;
|
||||
str += 3;
|
||||
}
|
||||
else if (strncmp (str, "hsla", 4) == 0)
|
||||
{
|
||||
has_alpha = TRUE;
|
||||
is_hsl = TRUE;
|
||||
str += 4;
|
||||
}
|
||||
else if (strncmp (str, "hsl", 3) == 0)
|
||||
{
|
||||
has_alpha = FALSE;
|
||||
is_hsl = TRUE;
|
||||
a = 1;
|
||||
str += 3;
|
||||
}
|
||||
@@ -291,10 +308,22 @@ gdk_rgba_parse (GdkRGBA *rgba,
|
||||
|
||||
if (rgba)
|
||||
{
|
||||
rgba->red = CLAMP (r, 0, 1);
|
||||
rgba->green = CLAMP (g, 0, 1);
|
||||
rgba->blue = CLAMP (b, 0, 1);
|
||||
rgba->alpha = CLAMP (a, 0, 1);
|
||||
if (is_hsl)
|
||||
{
|
||||
GdkHSLA hsla;
|
||||
hsla.hue = r * 255;
|
||||
hsla.saturation = CLAMP (g, 0, 1);
|
||||
hsla.lightness = CLAMP (b, 0, 1);
|
||||
hsla.alpha = CLAMP (a, 0, 1);
|
||||
_gdk_rgba_init_from_hsla (rgba, &hsla);
|
||||
}
|
||||
else
|
||||
{
|
||||
rgba->red = CLAMP (r, 0, 1);
|
||||
rgba->green = CLAMP (g, 0, 1);
|
||||
rgba->blue = CLAMP (b, 0, 1);
|
||||
rgba->alpha = CLAMP (a, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -462,6 +491,47 @@ parse_color_channel (GtkCssParser *parser,
|
||||
}
|
||||
}
|
||||
|
||||
static guint
|
||||
parse_hsla_color_channel (GtkCssParser *parser,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
{
|
||||
GdkHSLA *hsla = data;
|
||||
double dvalue;
|
||||
|
||||
switch (arg)
|
||||
{
|
||||
case 0:
|
||||
if (!gtk_css_parser_consume_number (parser, &dvalue))
|
||||
return 0;
|
||||
hsla->hue = dvalue;
|
||||
return 1;
|
||||
|
||||
case 1:
|
||||
if (!gtk_css_parser_consume_percentage (parser, &dvalue))
|
||||
return 0;
|
||||
hsla->saturation = CLAMP (dvalue, 0.0, 100.0) / 100.0;
|
||||
return 1;
|
||||
|
||||
case 2:
|
||||
if (!gtk_css_parser_consume_percentage (parser, &dvalue))
|
||||
return 0;
|
||||
hsla->lightness = CLAMP (dvalue, 0.0, 100.0) / 100.0;
|
||||
return 1;
|
||||
|
||||
case 3:
|
||||
if (!gtk_css_parser_consume_number (parser, &dvalue))
|
||||
return 0;
|
||||
|
||||
hsla->alpha = CLAMP (dvalue, 0.0, 1.0) / 1.0;
|
||||
return 1;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
rgba_init_chars (GdkRGBA *rgba,
|
||||
const char s[8])
|
||||
@@ -501,6 +571,18 @@ gdk_rgba_parser_parse (GtkCssParser *parser,
|
||||
{
|
||||
return gtk_css_parser_consume_function (parser, 4, 4, parse_color_channel, rgba);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "hsl") || gtk_css_token_is_function (token, "hsla"))
|
||||
{
|
||||
GdkHSLA hsla;
|
||||
|
||||
hsla.alpha = 1.0;
|
||||
|
||||
if (!gtk_css_parser_consume_function (parser, 3, 4, parse_hsla_color_channel, &hsla))
|
||||
return FALSE;
|
||||
|
||||
_gdk_rgba_init_from_hsla (rgba, &hsla);
|
||||
return TRUE;
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_UNRESTRICTED))
|
||||
{
|
||||
|
@@ -67,7 +67,7 @@ GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_rgba_parse (GdkRGBA *rgba,
|
||||
const char *spec);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
char * gdk_rgba_to_string (const GdkRGBA *rgba);
|
||||
char * gdk_rgba_to_string (const GdkRGBA *rgba) G_GNUC_MALLOC;
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -1065,87 +1065,23 @@ gdk_surface_get_mapped (GdkSurface *surface)
|
||||
return GDK_SURFACE_IS_MAPPED (surface);
|
||||
}
|
||||
|
||||
GdkGLContext *
|
||||
gdk_surface_get_shared_data_gl_context (GdkSurface *surface)
|
||||
{
|
||||
static int in_shared_data_creation;
|
||||
GdkDisplay *display;
|
||||
GdkGLContext *context;
|
||||
|
||||
if (in_shared_data_creation)
|
||||
return NULL;
|
||||
|
||||
in_shared_data_creation = 1;
|
||||
|
||||
display = gdk_surface_get_display (surface);
|
||||
context = (GdkGLContext *)g_object_get_data (G_OBJECT (display), "gdk-gl-shared-data-context");
|
||||
if (context == NULL)
|
||||
{
|
||||
GError *error = NULL;
|
||||
context = GDK_SURFACE_GET_CLASS (surface)->create_gl_context (surface, FALSE, NULL, &error);
|
||||
if (context == NULL)
|
||||
{
|
||||
g_warning ("Failed to create shared context: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
gdk_gl_context_realize (context, &error);
|
||||
if (context == NULL)
|
||||
{
|
||||
g_warning ("Failed to realize shared context: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
|
||||
g_object_set_data (G_OBJECT (display), "gdk-gl-shared-data-context", context);
|
||||
}
|
||||
|
||||
in_shared_data_creation = 0;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
GdkGLContext *
|
||||
gdk_surface_get_paint_gl_context (GdkSurface *surface,
|
||||
GError **error)
|
||||
GError **error)
|
||||
{
|
||||
GError *internal_error = NULL;
|
||||
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (surface->display, GL_DISABLE))
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("GL support disabled via GDK_DEBUG"));
|
||||
return NULL;
|
||||
}
|
||||
if (!gdk_display_prepare_gl (surface->display, error))
|
||||
return NULL;
|
||||
|
||||
if (surface->gl_paint_context == NULL)
|
||||
{
|
||||
GdkSurfaceClass *class = GDK_SURFACE_GET_CLASS (surface);
|
||||
|
||||
if (class->create_gl_context == NULL)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("The current backend does not support OpenGL"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
surface->gl_paint_context =
|
||||
class->create_gl_context (surface, TRUE, NULL, &internal_error);
|
||||
surface->gl_paint_context = gdk_surface_create_gl_context (surface, error);
|
||||
if (surface->gl_paint_context == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (internal_error != NULL)
|
||||
if (!gdk_gl_context_realize (surface->gl_paint_context, error))
|
||||
{
|
||||
g_propagate_error (error, internal_error);
|
||||
g_clear_object (&(surface->gl_paint_context));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gdk_gl_context_realize (surface->gl_paint_context, &internal_error);
|
||||
if (internal_error != NULL)
|
||||
{
|
||||
g_propagate_error (error, internal_error);
|
||||
g_clear_object (&(surface->gl_paint_context));
|
||||
g_clear_object (&surface->gl_paint_context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1170,19 +1106,13 @@ GdkGLContext *
|
||||
gdk_surface_create_gl_context (GdkSurface *surface,
|
||||
GError **error)
|
||||
{
|
||||
GdkGLContext *paint_context;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_SURFACE (surface), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
paint_context = gdk_surface_get_paint_gl_context (surface, error);
|
||||
if (paint_context == NULL)
|
||||
if (!gdk_display_prepare_gl (surface->display, error))
|
||||
return NULL;
|
||||
|
||||
return GDK_SURFACE_GET_CLASS (surface)->create_gl_context (surface,
|
||||
FALSE,
|
||||
paint_context,
|
||||
error);
|
||||
return gdk_gl_context_new_for_surface (surface);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -160,10 +160,6 @@ struct _GdkSurfaceClass
|
||||
|
||||
void (* set_opaque_region) (GdkSurface *surface,
|
||||
cairo_region_t *region);
|
||||
GdkGLContext *(*create_gl_context) (GdkSurface *surface,
|
||||
gboolean attached,
|
||||
GdkGLContext *share,
|
||||
GError **error);
|
||||
void (* request_layout) (GdkSurface *surface);
|
||||
gboolean (* compute_size) (GdkSurface *surface);
|
||||
};
|
||||
@@ -266,7 +262,6 @@ void _gdk_surface_update_size (GdkSurface *surface);
|
||||
|
||||
GdkGLContext * gdk_surface_get_paint_gl_context (GdkSurface *surface,
|
||||
GError **error);
|
||||
GdkGLContext * gdk_surface_get_shared_data_gl_context (GdkSurface *surface);
|
||||
|
||||
gboolean gdk_surface_handle_event (GdkEvent *event);
|
||||
GdkSeat * gdk_surface_get_seat_from_event (GdkSurface *surface,
|
||||
|
497
gdk/gdktexture.c
497
gdk/gdktexture.c
@@ -28,8 +28,8 @@
|
||||
* `GdkPixbuf`, or a Cairo surface, or other pixel data.
|
||||
*
|
||||
* The ownership of the pixel data is transferred to the `GdkTexture`
|
||||
* instance; you can only make a copy of it, via
|
||||
* [method@Gdk.Texture.download].
|
||||
* instance; you can only make a copy of it, via [method@Gdk.Texture.download]
|
||||
* or [method@Gdk.Texture.download_float].
|
||||
*
|
||||
* `GdkTexture` is an immutable object: That means you cannot change
|
||||
* anything about it other than increasing the reference count via
|
||||
@@ -41,11 +41,17 @@
|
||||
#include "gdktextureprivate.h"
|
||||
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdkpaintable.h"
|
||||
#include "gdksnapshot.h"
|
||||
|
||||
#include <graphene.h>
|
||||
#include "loaders/gdkpngprivate.h"
|
||||
#include "loaders/gdktiffprivate.h"
|
||||
#include "loaders/gdkjpegprivate.h"
|
||||
|
||||
G_DEFINE_QUARK (gdk-texture-error-quark, gdk_texture_error)
|
||||
|
||||
/* HACK: So we don't need to include any (not-yet-created) GSK or GTK headers */
|
||||
void
|
||||
@@ -108,20 +114,143 @@ gdk_texture_paintable_init (GdkPaintableInterface *iface)
|
||||
iface->get_intrinsic_height = gdk_texture_paintable_get_intrinsic_height;
|
||||
}
|
||||
|
||||
static GVariant *
|
||||
gdk_texture_icon_serialize (GIcon *icon)
|
||||
{
|
||||
GVariant *result;
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = gdk_texture_save_to_png_bytes (GDK_TEXTURE (icon));
|
||||
result = g_variant_new_from_bytes (G_VARIANT_TYPE_BYTESTRING, bytes, TRUE);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return g_variant_new ("(sv)", "bytes", result);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_icon_init (GIconIface *iface)
|
||||
{
|
||||
iface->hash = (guint (*) (GIcon *)) g_direct_hash;
|
||||
iface->equal = (gboolean (*) (GIcon *, GIcon *)) g_direct_equal;
|
||||
iface->serialize = gdk_texture_icon_serialize;
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_texture_loadable_icon_load (GLoadableIcon *icon,
|
||||
int size,
|
||||
char **type,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GInputStream *stream;
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = gdk_texture_save_to_png_bytes (GDK_TEXTURE (icon));
|
||||
stream = g_memory_input_stream_new_from_bytes (bytes);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
if (type)
|
||||
*type = NULL;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_loadable_icon_load_in_thread (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GInputStream *stream;
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = gdk_texture_save_to_png_bytes (source_object);
|
||||
stream = g_memory_input_stream_new_from_bytes (bytes);
|
||||
g_bytes_unref (bytes);
|
||||
g_task_return_pointer (task, stream, g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_loadable_icon_load_async (GLoadableIcon *icon,
|
||||
int size,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (icon, cancellable, callback, user_data);
|
||||
g_task_run_in_thread (task, gdk_texture_loadable_icon_load_in_thread);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
gdk_texture_loadable_icon_load_finish (GLoadableIcon *icon,
|
||||
GAsyncResult *res,
|
||||
char **type,
|
||||
GError **error)
|
||||
{
|
||||
GInputStream *result;
|
||||
|
||||
g_return_val_if_fail (g_task_is_valid (res, icon), NULL);
|
||||
|
||||
result = g_task_propagate_pointer (G_TASK (res), error);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
if (type)
|
||||
*type = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_loadable_icon_init (GLoadableIconIface *iface)
|
||||
{
|
||||
iface->load = gdk_texture_loadable_icon_load;
|
||||
iface->load_async = gdk_texture_loadable_icon_load_async;
|
||||
iface->load_finish = gdk_texture_loadable_icon_load_finish;
|
||||
}
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GdkTexture, gdk_texture, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
||||
gdk_texture_paintable_init))
|
||||
gdk_texture_paintable_init)
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_ICON,
|
||||
gdk_texture_icon_init)
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_LOADABLE_ICON, gdk_texture_loadable_icon_init))
|
||||
|
||||
#define GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD(obj,method) \
|
||||
g_critical ("Texture of type '%s' does not implement GdkTexture::" # method, G_OBJECT_TYPE_NAME (obj))
|
||||
|
||||
static void
|
||||
gdk_texture_real_download (GdkTexture *self,
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
static GdkTexture *
|
||||
gdk_texture_real_download_texture (GdkTexture *self)
|
||||
{
|
||||
GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD (self, download);
|
||||
GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD (self, download_texture);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_real_download (GdkTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkTexture *memory_texture;
|
||||
|
||||
memory_texture = gdk_texture_download_texture (texture);
|
||||
gdk_texture_download (memory_texture, data, stride);
|
||||
g_object_unref (memory_texture);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_real_download_float (GdkTexture *self,
|
||||
float *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkTexture *memory_texture;
|
||||
|
||||
memory_texture = gdk_texture_download_texture (self);
|
||||
gdk_texture_download_float (memory_texture, data, stride);
|
||||
g_object_unref (memory_texture);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -187,7 +316,9 @@ gdk_texture_class_init (GdkTextureClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
klass->download_texture = gdk_texture_real_download_texture;
|
||||
klass->download = gdk_texture_real_download;
|
||||
klass->download_float = gdk_texture_real_download_float;
|
||||
|
||||
gobject_class->set_property = gdk_texture_set_property;
|
||||
gobject_class->get_property = gdk_texture_get_property;
|
||||
@@ -263,7 +394,7 @@ gdk_texture_new_for_surface (cairo_surface_t *surface)
|
||||
|
||||
texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface),
|
||||
cairo_image_surface_get_height (surface),
|
||||
GDK_MEMORY_CAIRO_FORMAT_ARGB32,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
bytes,
|
||||
cairo_image_surface_get_stride (surface));
|
||||
|
||||
@@ -325,18 +456,23 @@ gdk_texture_new_for_pixbuf (GdkPixbuf *pixbuf)
|
||||
GdkTexture *
|
||||
gdk_texture_new_from_resource (const char *resource_path)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GBytes *bytes;
|
||||
GdkTexture *texture;
|
||||
GdkPixbuf *pixbuf;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_val_if_fail (resource_path != NULL, NULL);
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_resource (resource_path, &error);
|
||||
if (pixbuf == NULL)
|
||||
g_error ("Resource path %s is not a valid image: %s", resource_path, error->message);
|
||||
bytes = g_resources_lookup_data (resource_path, 0, &error);
|
||||
if (bytes != NULL)
|
||||
{
|
||||
texture = gdk_texture_new_from_bytes (bytes, &error);
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
else
|
||||
texture = NULL;
|
||||
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
g_object_unref (pixbuf);
|
||||
if (texture == NULL)
|
||||
g_error ("Resource path %s s not a valid image: %s", resource_path, error->message);
|
||||
|
||||
return texture;
|
||||
}
|
||||
@@ -359,17 +495,65 @@ GdkTexture *
|
||||
gdk_texture_new_from_file (GFile *file,
|
||||
GError **error)
|
||||
{
|
||||
GBytes *bytes;
|
||||
GdkTexture *texture;
|
||||
GdkPixbuf *pixbuf;
|
||||
GInputStream *stream;
|
||||
|
||||
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
stream = G_INPUT_STREAM (g_file_read (file, NULL, error));
|
||||
if (stream == NULL)
|
||||
bytes = g_file_load_bytes (file, NULL, NULL, error);
|
||||
if (bytes == NULL)
|
||||
return NULL;
|
||||
|
||||
texture = gdk_texture_new_from_bytes (bytes, error);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_texture_can_load (GBytes *bytes)
|
||||
{
|
||||
return gdk_is_png (bytes) ||
|
||||
gdk_is_jpeg (bytes) ||
|
||||
gdk_is_tiff (bytes);
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
gdk_texture_new_from_bytes_internal (GBytes *bytes,
|
||||
GError **error)
|
||||
{
|
||||
if (gdk_is_png (bytes))
|
||||
{
|
||||
return gdk_load_png (bytes, error);
|
||||
}
|
||||
else if (gdk_is_jpeg (bytes))
|
||||
{
|
||||
return gdk_load_jpeg (bytes, error);
|
||||
}
|
||||
else if (gdk_is_tiff (bytes))
|
||||
{
|
||||
return gdk_load_tiff (bytes, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_UNSUPPORTED_FORMAT,
|
||||
_("Unknown image format."));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
gdk_texture_new_from_bytes_pixbuf (GBytes *bytes,
|
||||
GError **error)
|
||||
{
|
||||
GInputStream *stream;
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkTexture *texture;
|
||||
|
||||
stream = g_memory_input_stream_new_from_bytes (bytes);
|
||||
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, error);
|
||||
g_object_unref (stream);
|
||||
if (pixbuf == NULL)
|
||||
@@ -381,6 +565,82 @@ gdk_texture_new_from_file (GFile *file,
|
||||
return texture;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gdk_texture_new_from_bytes:
|
||||
* @bytes: a `GBytes` containing the data to load
|
||||
* @error: Return location for an error
|
||||
*
|
||||
* Creates a new texture by loading an image from memory,
|
||||
*
|
||||
* The file format is detected automatically. The supported formats
|
||||
* are PNG and JPEG, though more formats might be available.
|
||||
*
|
||||
* If %NULL is returned, then @error will be set.
|
||||
*
|
||||
* Return value: A newly-created `GdkTexture`
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
GdkTexture *
|
||||
gdk_texture_new_from_bytes (GBytes *bytes,
|
||||
GError **error)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
GError *internal_error = NULL;
|
||||
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
texture = gdk_texture_new_from_bytes_internal (bytes, &internal_error);
|
||||
if (texture)
|
||||
return texture;
|
||||
|
||||
if (!g_error_matches (internal_error, GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_UNSUPPORTED_CONTENT) &&
|
||||
!g_error_matches (internal_error, GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_UNSUPPORTED_FORMAT))
|
||||
{
|
||||
g_propagate_error (error, internal_error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_clear_error (&internal_error);
|
||||
|
||||
return gdk_texture_new_from_bytes_pixbuf (bytes, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_new_from_filename:
|
||||
* @path: (type filename): the filename to load
|
||||
* @error: Return location for an error
|
||||
*
|
||||
* Creates a new texture by loading an image from a file.
|
||||
*
|
||||
* The file format is detected automatically. The supported formats
|
||||
* are PNG and JPEG, though more formats might be available.
|
||||
*
|
||||
* If %NULL is returned, then @error will be set.
|
||||
*
|
||||
* Return value: A newly-created `GdkTexture`
|
||||
*/
|
||||
GdkTexture *
|
||||
gdk_texture_new_from_filename (const char *path,
|
||||
GError **error)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
GFile *file;
|
||||
|
||||
g_return_val_if_fail (path, NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
file = g_file_new_for_path (path);
|
||||
|
||||
texture = gdk_texture_new_from_file (file, error);
|
||||
|
||||
g_object_unref (file);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_get_width: (attributes org.gtk.Method.get_property=width)
|
||||
* @texture: a `GdkTexture`
|
||||
@@ -435,20 +695,6 @@ gdk_texture_download_surface (GdkTexture *texture)
|
||||
return surface;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_texture_download_area (GdkTexture *texture,
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
g_assert (area->x >= 0);
|
||||
g_assert (area->y >= 0);
|
||||
g_assert (area->x + area->width <= texture->width);
|
||||
g_assert (area->y + area->height <= texture->height);
|
||||
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download (texture, area, data, stride);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_download:
|
||||
* @texture: a `GdkTexture`
|
||||
@@ -485,10 +731,62 @@ gdk_texture_download (GdkTexture *texture,
|
||||
g_return_if_fail (data != NULL);
|
||||
g_return_if_fail (stride >= gdk_texture_get_width (texture) * 4);
|
||||
|
||||
gdk_texture_download_area (texture,
|
||||
&(GdkRectangle) { 0, 0, texture->width, texture->height },
|
||||
data,
|
||||
stride);
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download (texture, data, stride);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_download_float:
|
||||
* @texture: a `GdkTexture`
|
||||
* @data: (array): pointer to enough memory to be filled with the
|
||||
* downloaded data of @texture
|
||||
* @stride: rowstride in elements, will usually be equal to
|
||||
* gdk_texture_get_width() * 4
|
||||
*
|
||||
* Downloads the @texture into local memory in a high dynamic range format.
|
||||
*
|
||||
* This may be an expensive operation, as the actual texture data
|
||||
* may reside on a GPU or on a remote display server and because the data
|
||||
* may need to be upsampled if it was not already available in this
|
||||
* format.
|
||||
*
|
||||
* You may want to use [method@Gdk.Texture.download] instead if you don't
|
||||
* need high dynamic range support.
|
||||
*
|
||||
* The data format of the downloaded data is equivalent to
|
||||
* GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED, so every downloaded
|
||||
* pixel requires 16 bytes of memory.
|
||||
*
|
||||
* Note that the caller is responsible to provide sufficiently
|
||||
* aligned memory to access the resulting data directly as floats.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
void
|
||||
gdk_texture_download_float (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_TEXTURE (texture));
|
||||
g_return_if_fail (data != NULL);
|
||||
g_return_if_fail (stride >= gdk_texture_get_width (texture) * 4);
|
||||
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download_float (texture, data, stride);
|
||||
}
|
||||
|
||||
GdkTexture *
|
||||
gdk_texture_download_texture (GdkTexture *texture)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
|
||||
|
||||
g_object_ref (texture);
|
||||
while (!GDK_IS_MEMORY_TEXTURE (texture))
|
||||
{
|
||||
GdkTexture *downloaded = GDK_TEXTURE_GET_CLASS (texture)->download_texture (texture);
|
||||
g_object_unref (texture);
|
||||
texture = downloaded;
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -540,7 +838,8 @@ gdk_texture_get_render_data (GdkTexture *self,
|
||||
* This is a utility function intended for debugging and testing.
|
||||
* If you want more control over formats, proper error handling or
|
||||
* want to store to a `GFile` or other location, you might want to
|
||||
* look into using the gdk-pixbuf library.
|
||||
* use [method@Gdk.Texture.save_to_png_bytes] or look into the
|
||||
* gdk-pixbuf library.
|
||||
*
|
||||
* Returns: %TRUE if saving succeeded, %FALSE on failure.
|
||||
*/
|
||||
@@ -548,30 +847,110 @@ gboolean
|
||||
gdk_texture_save_to_png (GdkTexture *texture,
|
||||
const char *filename)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_status_t status;
|
||||
GBytes *bytes;
|
||||
gboolean result;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), FALSE);
|
||||
g_return_val_if_fail (filename != NULL, FALSE);
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
gdk_texture_download (texture,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_stride (surface));
|
||||
cairo_surface_mark_dirty (surface);
|
||||
|
||||
status = cairo_surface_write_to_png (surface, filename);
|
||||
|
||||
if (status != CAIRO_STATUS_SUCCESS ||
|
||||
cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
|
||||
result = FALSE;
|
||||
else
|
||||
result = TRUE;
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
bytes = gdk_save_png (texture);
|
||||
result = g_file_set_contents (filename,
|
||||
g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes),
|
||||
NULL);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_save_to_png_bytes:
|
||||
* @texture: a `GdkTexture`
|
||||
*
|
||||
* Store the given @texture in memory as a PNG file.
|
||||
* Use [ctor@Gdk.Texture.new_from_bytes] to read it back.
|
||||
*
|
||||
* If you want to serialize a texture, this is a convenient and
|
||||
* portable way to do that.
|
||||
*
|
||||
* If you need more control over the generated image, such as
|
||||
* attaching metadata, you should look into an image handling
|
||||
* library such as the gdk-pixbuf library.
|
||||
*
|
||||
* If you are dealing with high dynamic range float data, you
|
||||
* might also want to consider [method@Gdk.Texture.save_to_tiff_bytes]
|
||||
* instead.
|
||||
*
|
||||
* Returns: a newly allocated `GBytes` containing PNG data
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
GBytes *
|
||||
gdk_texture_save_to_png_bytes (GdkTexture *texture)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
|
||||
|
||||
return gdk_save_png (texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_save_to_tiff:
|
||||
* @texture: a `GdkTexture`
|
||||
* @filename: (type filename): the filename to store to
|
||||
*
|
||||
* Store the given @texture to the @filename as a TIFF file.
|
||||
*
|
||||
* GTK will attempt to store data without loss.
|
||||
* Returns: %TRUE if saving succeeded, %FALSE on failure.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
gboolean
|
||||
gdk_texture_save_to_tiff (GdkTexture *texture,
|
||||
const char *filename)
|
||||
{
|
||||
GBytes *bytes;
|
||||
gboolean result;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), FALSE);
|
||||
g_return_val_if_fail (filename != NULL, FALSE);
|
||||
|
||||
bytes = gdk_save_tiff (texture);
|
||||
result = g_file_set_contents (filename,
|
||||
g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes),
|
||||
NULL);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_save_to_tiff_bytes:
|
||||
* @texture: a `GdkTexture`
|
||||
*
|
||||
* Store the given @texture in memory as a TIFF file.
|
||||
*
|
||||
* Use [ctor@Gdk.Texture.new_from_bytes] to read it back.
|
||||
*
|
||||
* This function is intended to store a representation of the
|
||||
* texture's data that is as accurate as possible. This is
|
||||
* particularly relevant when working with high dynamic range
|
||||
* images and floating-point texture data.
|
||||
*
|
||||
* If that is not your concern and you are interested in a
|
||||
* smaller size and a more portable format, you might want to
|
||||
* use [method@Gdk.Texture.save_to_png_bytes].
|
||||
*
|
||||
* Returns: a newly allocated `GBytes` containing TIFF data
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
GBytes *
|
||||
gdk_texture_save_to_tiff_bytes (GdkTexture *texture)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
|
||||
|
||||
return gdk_save_tiff (texture);
|
||||
}
|
||||
|
||||
|
@@ -38,6 +38,30 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkTexture, g_object_unref)
|
||||
|
||||
typedef struct _GdkTextureClass GdkTextureClass;
|
||||
|
||||
#define GDK_TEXTURE_ERROR (gdk_texture_error_quark ())
|
||||
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GQuark gdk_texture_error_quark (void);
|
||||
|
||||
/**
|
||||
* GdkTextureError:
|
||||
* @GDK_TEXTURE_ERROR_TOO_LARGE: Not enough memory to handle this image
|
||||
* @GDK_TEXTURE_ERROR_CORRUPT_IMAGE: The image data appears corrupted
|
||||
* @GDK_TEXTURE_ERROR_UNSUPPORTED_CONTENT: The image contains features
|
||||
* that cannot be loaded
|
||||
* @GDK_TEXTURE_ERROR_UNSUPPORTED_FORMAT: The image format is not supported
|
||||
*
|
||||
* Possible errors that can be returned by `GdkTexture` constructors.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GDK_TEXTURE_ERROR_TOO_LARGE,
|
||||
GDK_TEXTURE_ERROR_CORRUPT_IMAGE,
|
||||
GDK_TEXTURE_ERROR_UNSUPPORTED_CONTENT,
|
||||
GDK_TEXTURE_ERROR_UNSUPPORTED_FORMAT,
|
||||
} GdkTextureError;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_texture_get_type (void) G_GNUC_CONST;
|
||||
@@ -49,6 +73,12 @@ GdkTexture * gdk_texture_new_from_resource (const char
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkTexture * gdk_texture_new_from_file (GFile *file,
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GdkTexture * gdk_texture_new_from_filename (const char *path,
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GdkTexture * gdk_texture_new_from_bytes (GBytes *bytes,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
int gdk_texture_get_width (GdkTexture *texture) G_GNUC_PURE;
|
||||
@@ -59,9 +89,20 @@ GDK_AVAILABLE_IN_ALL
|
||||
void gdk_texture_download (GdkTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
void gdk_texture_download_float (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_texture_save_to_png (GdkTexture *texture,
|
||||
const char *filename);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GBytes * gdk_texture_save_to_png_bytes (GdkTexture *texture);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
gboolean gdk_texture_save_to_tiff (GdkTexture *texture,
|
||||
const char *filename);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GBytes * gdk_texture_save_to_tiff_bytes (GdkTexture *texture);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@@ -24,21 +24,23 @@ struct _GdkTexture
|
||||
struct _GdkTextureClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* mandatory: Download into a GdkMemoryTexture */
|
||||
GdkTexture * (* download_texture) (GdkTexture *texture);
|
||||
/* optional */
|
||||
void (* download) (GdkTexture *texture,
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
void (* download_float) (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride);
|
||||
};
|
||||
|
||||
gpointer gdk_texture_new (const GdkTextureClass *klass,
|
||||
int width,
|
||||
int height);
|
||||
gboolean gdk_texture_can_load (GBytes *bytes);
|
||||
|
||||
GdkTexture * gdk_texture_new_for_surface (cairo_surface_t *surface);
|
||||
cairo_surface_t * gdk_texture_download_surface (GdkTexture *texture);
|
||||
void gdk_texture_download_area (GdkTexture *texture,
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
/* NB: GdkMemoryTexture */
|
||||
GdkTexture * gdk_texture_download_texture (GdkTexture *texture);
|
||||
|
||||
gboolean gdk_texture_set_render_data (GdkTexture *self,
|
||||
gpointer key,
|
||||
|
@@ -78,6 +78,13 @@ gdk_toplevel_default_show_window_menu (GdkToplevel *toplevel,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_toplevel_default_titlebar_gesture (GdkToplevel *toplevel,
|
||||
GdkTitlebarGesture gesture)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_toplevel_default_supports_edge_constraints (GdkToplevel *toplevel)
|
||||
{
|
||||
@@ -114,6 +121,7 @@ gdk_toplevel_default_init (GdkToplevelInterface *iface)
|
||||
iface->supports_edge_constraints = gdk_toplevel_default_supports_edge_constraints;
|
||||
iface->inhibit_system_shortcuts = gdk_toplevel_default_inhibit_system_shortcuts;
|
||||
iface->restore_system_shortcuts = gdk_toplevel_default_restore_system_shortcuts;
|
||||
iface->titlebar_gesture = gdk_toplevel_default_titlebar_gesture;
|
||||
|
||||
/**
|
||||
* GdkToplevel:state: (attributes org.gtk.Property.get=gdk_toplevel_get_state)
|
||||
@@ -716,3 +724,13 @@ gdk_toplevel_begin_move (GdkToplevel *toplevel,
|
||||
x, y,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_toplevel_titlebar_gesture (GdkToplevel *toplevel,
|
||||
GdkTitlebarGesture gesture)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), FALSE);
|
||||
|
||||
return GDK_TOPLEVEL_GET_IFACE (toplevel)->titlebar_gesture (toplevel,
|
||||
gesture);
|
||||
}
|
||||
|
@@ -115,6 +115,13 @@ typedef enum
|
||||
GDK_TOPLEVEL_STATE_LEFT_RESIZABLE = 1 << 15
|
||||
} GdkToplevelState;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GDK_TITLEBAR_GESTURE_DOUBLE_CLICK = 1,
|
||||
GDK_TITLEBAR_GESTURE_RIGHT_CLICK = 2,
|
||||
GDK_TITLEBAR_GESTURE_MIDDLE_CLICK = 3
|
||||
} GdkTitlebarGesture;
|
||||
|
||||
|
||||
#define GDK_TYPE_TOPLEVEL (gdk_toplevel_get_type ())
|
||||
|
||||
@@ -196,6 +203,10 @@ void gdk_toplevel_begin_move (GdkToplevel *toplevel,
|
||||
double y,
|
||||
guint32 timestamp);
|
||||
|
||||
GDK_AVAILABLE_IN_4_4
|
||||
gboolean gdk_toplevel_titlebar_gesture (GdkToplevel *toplevel,
|
||||
GdkTitlebarGesture gesture);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_TOPLEVEL_H__ */
|
||||
|
@@ -38,6 +38,8 @@ struct _GdkToplevelInterface
|
||||
double x,
|
||||
double y,
|
||||
guint32 timestamp);
|
||||
gboolean (* titlebar_gesture) (GdkToplevel *toplevel,
|
||||
GdkTitlebarGesture gesture);
|
||||
};
|
||||
|
||||
typedef enum
|
||||
|
@@ -94,6 +94,14 @@
|
||||
*/
|
||||
#define GDK_VERSION_4_4 (G_ENCODE_VERSION (4, 4))
|
||||
|
||||
/**
|
||||
* GDK_VERSION_4_6:
|
||||
*
|
||||
* A macro that evaluates to the 4.6 version of GDK, in a format
|
||||
* that can be used by the C pre-processor.
|
||||
*/
|
||||
#define GDK_VERSION_4_6 (G_ENCODE_VERSION (4, 6))
|
||||
|
||||
|
||||
/* evaluates to the current stable version; for development cycles,
|
||||
* this means the next stable target, with a hard backstop to the
|
||||
@@ -221,4 +229,18 @@
|
||||
# define GDK_DEPRECATED_IN_4_4_FOR(f) _GDK_EXTERN
|
||||
#endif
|
||||
|
||||
#if GDK_VERSION_MAX_ALLOWED < GDK_VERSION_4_6
|
||||
# define GDK_AVAILABLE_IN_4_6 GDK_UNAVAILABLE(4, 6)
|
||||
#else
|
||||
# define GDK_AVAILABLE_IN_4_6 _GDK_EXTERN
|
||||
#endif
|
||||
|
||||
#if GDK_VERSION_MIN_REQUIRED >= GDK_VERSION_4_6
|
||||
# define GDK_DEPRECATED_IN_4_6 GDK_DEPRECATED
|
||||
# define GDK_DEPRECATED_IN_4_6_FOR(f) GDK_DEPRECATED_FOR(f)
|
||||
#else
|
||||
# define GDK_DEPRECATED_IN_4_6 _GDK_EXTERN
|
||||
# define GDK_DEPRECATED_IN_4_6_FOR(f) _GDK_EXTERN
|
||||
#endif
|
||||
|
||||
#endif /* __GDK_VERSION_MACROS_H__ */
|
||||
|
@@ -117,104 +117,104 @@ gdk_vulkan_strerror (VkResult result)
|
||||
switch (result)
|
||||
{
|
||||
case VK_SUCCESS:
|
||||
return "Command successfully completed.";
|
||||
return "Command successfully completed. (VK_SUCCESS)";
|
||||
case VK_NOT_READY:
|
||||
return "A fence or query has not yet completed.";
|
||||
return "A fence or query has not yet completed. (VK_NOT_READY)";
|
||||
case VK_TIMEOUT:
|
||||
return "A wait operation has not completed in the specified time.";
|
||||
return "A wait operation has not completed in the specified time. (VK_TIMEOUT)";
|
||||
case VK_EVENT_SET:
|
||||
return "An event is signaled.";
|
||||
return "An event is signaled. (VK_EVENT_SET)";
|
||||
case VK_EVENT_RESET:
|
||||
return "An event is unsignaled.";
|
||||
return "An event is unsignaled. (VK_EVENT_RESET)";
|
||||
case VK_INCOMPLETE:
|
||||
return "A return array was too small for the result.";
|
||||
return "A return array was too small for the result. (VK_INCOMPLETE)";
|
||||
case VK_SUBOPTIMAL_KHR:
|
||||
return "A swapchain no longer matches the surface properties exactly, but can still be used to present to the surface successfully.";
|
||||
return "A swapchain no longer matches the surface properties exactly, but can still be used to present to the surface successfully. (VK_SUBOPTIMAL_KHR)";
|
||||
case VK_ERROR_OUT_OF_HOST_MEMORY:
|
||||
return "A host memory allocation has failed.";
|
||||
return "A host memory allocation has failed. (VK_ERROR_OUT_OF_HOST_MEMORY)";
|
||||
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
|
||||
return "A device memory allocation has failed.";
|
||||
return "A device memory allocation has failed. (VK_ERROR_OUT_OF_DEVICE_MEMORY)";
|
||||
case VK_ERROR_INITIALIZATION_FAILED:
|
||||
return "Initialization of an object could not be completed for implementation-specific reasons.";
|
||||
return "Initialization of an object could not be completed for implementation-specific reasons. (VK_ERROR_INITIALIZATION_FAILED)";
|
||||
case VK_ERROR_DEVICE_LOST:
|
||||
return "The logical or physical device has been lost.";
|
||||
return "The logical or physical device has been lost. (VK_ERROR_DEVICE_LOST)";
|
||||
case VK_ERROR_MEMORY_MAP_FAILED:
|
||||
return "Mapping of a memory object has failed.";
|
||||
return "Mapping of a memory object has failed. (VK_ERROR_MEMORY_MAP_FAILED)";
|
||||
case VK_ERROR_LAYER_NOT_PRESENT:
|
||||
return "A requested layer is not present or could not be loaded.";
|
||||
return "A requested layer is not present or could not be loaded. (VK_ERROR_LAYER_NOT_PRESENT)";
|
||||
case VK_ERROR_EXTENSION_NOT_PRESENT:
|
||||
return "A requested extension is not supported.";
|
||||
return "A requested extension is not supported. (VK_ERROR_EXTENSION_NOT_PRESENT)";
|
||||
case VK_ERROR_FEATURE_NOT_PRESENT:
|
||||
return "A requested feature is not supported.";
|
||||
return "A requested feature is not supported. (VK_ERROR_FEATURE_NOT_PRESENT)";
|
||||
case VK_ERROR_INCOMPATIBLE_DRIVER:
|
||||
return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible for implementation-specific reasons.";
|
||||
return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible for implementation-specific reasons. (VK_ERROR_INCOMPATIBLE_DRIVER)";
|
||||
case VK_ERROR_TOO_MANY_OBJECTS:
|
||||
return "Too many objects of the type have already been created.";
|
||||
return "Too many objects of the type have already been created. (VK_ERROR_TOO_MANY_OBJECTS)";
|
||||
case VK_ERROR_FORMAT_NOT_SUPPORTED:
|
||||
return "A requested format is not supported on this device.";
|
||||
return "A requested format is not supported on this device. (VK_ERROR_FORMAT_NOT_SUPPORTED)";
|
||||
#if VK_HEADER_VERSION >= 24
|
||||
case VK_ERROR_FRAGMENTED_POOL:
|
||||
return "A requested pool allocation has failed due to fragmentation of the pool’s memory.";
|
||||
return "A requested pool allocation has failed due to fragmentation of the pool’s memory. (VK_ERROR_FRAGMENTED_POOL)";
|
||||
#endif
|
||||
case VK_ERROR_SURFACE_LOST_KHR:
|
||||
return "A surface is no longer available.";
|
||||
return "A surface is no longer available. (VK_ERROR_SURFACE_LOST_KHR)";
|
||||
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
|
||||
return "The requested window is already in use by Vulkan or another API in a manner which prevents it from being used again.";
|
||||
return "The requested window is already in use by Vulkan or another API in a manner which prevents it from being used again. (VK_ERROR_NATIVE_WINDOW_IN_USE_KHR)";
|
||||
case VK_ERROR_OUT_OF_DATE_KHR:
|
||||
return "A surface has changed in such a way that it is no longer compatible with the swapchain.";
|
||||
return "A surface has changed in such a way that it is no longer compatible with the swapchain. (VK_ERROR_OUT_OF_DATE_KHR)";
|
||||
case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
|
||||
return "The display used by a swapchain does not use the same presentable image layout, or is incompatible in a way that prevents sharing an image.";
|
||||
return "The display used by a swapchain does not use the same presentable image layout, or is incompatible in a way that prevents sharing an image. (VK_ERROR_INCOMPATIBLE_DISPLAY_KHR)";
|
||||
case VK_ERROR_VALIDATION_FAILED_EXT:
|
||||
return "The application caused the validation layer to fail.";
|
||||
return "The application caused the validation layer to fail. (VK_ERROR_VALIDATION_FAILED_EXT)";
|
||||
case VK_ERROR_INVALID_SHADER_NV:
|
||||
return "One or more shaders failed to compile or link.";
|
||||
return "One or more shaders failed to compile or link. (VK_ERROR_INVALID_SHADER_NV)";
|
||||
#if VK_HEADER_VERSION >= 39
|
||||
case VK_ERROR_OUT_OF_POOL_MEMORY_KHR:
|
||||
return "A pool memory allocation has failed.";
|
||||
return "A pool memory allocation has failed. (VK_ERROR_OUT_OF_POOL_MEMORY_KHR)";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 54
|
||||
case VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR:
|
||||
return "An external handle is not a valid handle of the specified type.";
|
||||
return "An external handle is not a valid handle of the specified type. (VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR)";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 64
|
||||
case VK_ERROR_NOT_PERMITTED_EXT:
|
||||
return "The caller does not have sufficient privileges.";
|
||||
return "The caller does not have sufficient privileges. (VK_ERROR_NOT_PERMITTED_EXT)";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 72
|
||||
case VK_ERROR_FRAGMENTATION_EXT:
|
||||
return "A descriptor pool creation has failed due to fragmentation";
|
||||
return "A descriptor pool creation has failed due to fragmentation. (VK_ERROR_FRAGMENTATION_EXT)";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 89
|
||||
case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
|
||||
return "Invalid DRM format modifier plane layout";
|
||||
return "Invalid DRM format modifier plane layout (VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT)";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 97
|
||||
case VK_ERROR_INVALID_DEVICE_ADDRESS_EXT:
|
||||
return "Invalid device address";
|
||||
return "Invalid device address (VK_ERROR_INVALID_DEVICE_ADDRESS_EXT)";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 105
|
||||
case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT:
|
||||
return "An operation on a swapchain created with VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT failed as it did not have exclusive full-screen access.";
|
||||
return "An operation on a swapchain created with VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT failed as it did not have exclusive full-screen access. (VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 131
|
||||
case VK_ERROR_UNKNOWN:
|
||||
return "An unknown error has occurred; either the application has provided invalid input, or an implementation failure has occurred.";
|
||||
return "An unknown error has occurred; either the application has provided invalid input, or an implementation failure has occurred. (VK_ERROR_UNKNOWN)";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 135
|
||||
#if VK_HEADER_VERSION < 162
|
||||
case VK_ERROR_INCOMPATIBLE_VERSION_KHR:
|
||||
return "This error was removed by the Vulkan gods.";
|
||||
return "This error was removed by the Vulkan gods. (VK_ERROR_INCOMPATIBLE_VERSION_KHR)";
|
||||
#endif
|
||||
case VK_THREAD_IDLE_KHR:
|
||||
return "A deferred operation is not complete but there is currently no work for this thread to do at the time of this call.";
|
||||
return "A deferred operation is not complete but there is currently no work for this thread to do at the time of this call. (VK_THREAD_IDLE_KHR)";
|
||||
case VK_THREAD_DONE_KHR:
|
||||
return "A deferred operation is not complete but there is no work remaining to assign to additional threads.";
|
||||
return "A deferred operation is not complete but there is no work remaining to assign to additional threads. (VK_THREAD_DONE_KHR)";
|
||||
case VK_OPERATION_DEFERRED_KHR:
|
||||
return "A deferred operation was requested and at least some of the work was deferred.";
|
||||
return "A deferred operation was requested and at least some of the work was deferred. (VK_OPERATION_DEFERRED_KHR)";
|
||||
case VK_OPERATION_NOT_DEFERRED_KHR:
|
||||
return "A deferred operation was requested and no operations were deferred.";
|
||||
return "A deferred operation was requested and no operations were deferred. (VK_OPERATION_NOT_DEFERRED_KHR)";
|
||||
case VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT:
|
||||
return "A requested pipeline creation would have required compilation, but the application requested compilation to not be performed.";
|
||||
return "A requested pipeline creation would have required compilation, but the application requested compilation to not be performed. (VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT)";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION < 140
|
||||
case VK_RESULT_RANGE_SIZE:
|
||||
|
334
gdk/loaders/gdkjpeg.c
Normal file
334
gdk/loaders/gdkjpeg.c
Normal file
@@ -0,0 +1,334 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2021 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkjpegprivate.h"
|
||||
|
||||
#include "gdkintl.h"
|
||||
#include "gdktexture.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
|
||||
#include "gdkprofilerprivate.h"
|
||||
|
||||
#include <jpeglib.h>
|
||||
#include <jerror.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
/* {{{ Error handling */
|
||||
|
||||
/* No sigsetjmp on Windows */
|
||||
#ifndef HAVE_SIGSETJMP
|
||||
#define sigjmp_buf jmp_buf
|
||||
#define sigsetjmp(jb, x) setjmp(jb)
|
||||
#define siglongjmp longjmp
|
||||
#endif
|
||||
|
||||
struct error_handler_data {
|
||||
struct jpeg_error_mgr pub;
|
||||
sigjmp_buf setjmp_buffer;
|
||||
GError **error;
|
||||
};
|
||||
|
||||
static void
|
||||
fatal_error_handler (j_common_ptr cinfo)
|
||||
{
|
||||
struct error_handler_data *errmgr;
|
||||
char buffer[JMSG_LENGTH_MAX];
|
||||
|
||||
errmgr = (struct error_handler_data *) cinfo->err;
|
||||
|
||||
cinfo->err->format_message (cinfo, buffer);
|
||||
|
||||
if (errmgr->error && *errmgr->error == NULL)
|
||||
g_set_error (errmgr->error,
|
||||
GDK_TEXTURE_ERROR,
|
||||
GDK_TEXTURE_ERROR_CORRUPT_IMAGE,
|
||||
_("Error interpreting JPEG image file (%s)"), buffer);
|
||||
|
||||
siglongjmp (errmgr->setjmp_buffer, 1);
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static void
|
||||
output_message_handler (j_common_ptr cinfo)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Format conversion */
|
||||
|
||||
static void
|
||||
convert_rgba_to_rgb (guchar *data,
|
||||
int width,
|
||||
int height,
|
||||
int stride)
|
||||
{
|
||||
gsize x, y;
|
||||
guchar *src, *dest;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
src = data;
|
||||
dest = data;
|
||||
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
guint32 pixel;
|
||||
|
||||
memcpy (&pixel, src, sizeof (guint32));
|
||||
|
||||
dest[0] = (pixel & 0x00ff0000) >> 16;
|
||||
dest[1] = (pixel & 0x0000ff00) >> 8;
|
||||
dest[2] = (pixel & 0x000000ff) >> 0;
|
||||
|
||||
dest += 3;
|
||||
src += 4;
|
||||
}
|
||||
|
||||
data += stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
convert_grayscale_to_rgb (guchar *data,
|
||||
int width,
|
||||
int height,
|
||||
int stride)
|
||||
{
|
||||
gsize x, y;
|
||||
guchar *dest, *src;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
src = data + width;
|
||||
dest = data + 3 * width;
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
dest -= 3;
|
||||
src -= 1;
|
||||
dest[0] = *src;
|
||||
dest[1] = *src;
|
||||
dest[2] = *src;
|
||||
}
|
||||
data += stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
convert_cmyk_to_rgba (guchar *data,
|
||||
int width,
|
||||
int height,
|
||||
int stride)
|
||||
{
|
||||
gsize x, r;
|
||||
guchar *dest;
|
||||
|
||||
for (r = 0; r < height; r++)
|
||||
{
|
||||
dest = data;
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
int c, m, y, k;
|
||||
|
||||
c = dest[0];
|
||||
m = dest[1];
|
||||
y = dest[2];
|
||||
k = dest[3];
|
||||
dest[0] = k * c / 255;
|
||||
dest[1] = k * m / 255;
|
||||
dest[2] = k * y / 255;
|
||||
dest[3] = 255;
|
||||
dest += 4;
|
||||
}
|
||||
data += stride;
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
|
||||
GdkTexture *
|
||||
gdk_load_jpeg (GBytes *input_bytes,
|
||||
GError **error)
|
||||
{
|
||||
struct jpeg_decompress_struct info;
|
||||
struct error_handler_data jerr;
|
||||
guint width, height, stride;
|
||||
unsigned char *data;
|
||||
unsigned char *row[1];
|
||||
GBytes *bytes;
|
||||
GdkTexture *texture;
|
||||
GdkMemoryFormat format;
|
||||
G_GNUC_UNUSED guint64 before = GDK_PROFILER_CURRENT_TIME;
|
||||
|
||||
info.err = jpeg_std_error (&jerr.pub);
|
||||
jerr.pub.error_exit = fatal_error_handler;
|
||||
jerr.pub.output_message = output_message_handler;
|
||||
jerr.error = error;
|
||||
|
||||
if (sigsetjmp (jerr.setjmp_buffer, 1))
|
||||
{
|
||||
jpeg_destroy_decompress (&info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jpeg_create_decompress (&info);
|
||||
|
||||
jpeg_mem_src (&info,
|
||||
g_bytes_get_data (input_bytes, NULL),
|
||||
g_bytes_get_size (input_bytes));
|
||||
|
||||
jpeg_read_header (&info, TRUE);
|
||||
jpeg_start_decompress (&info);
|
||||
|
||||
width = info.output_width;
|
||||
height = info.output_height;
|
||||
|
||||
switch ((int)info.out_color_space)
|
||||
{
|
||||
case JCS_GRAYSCALE:
|
||||
case JCS_RGB:
|
||||
stride = 3 * width;
|
||||
data = g_try_malloc_n (stride, height);
|
||||
format = GDK_MEMORY_R8G8B8;
|
||||
break;
|
||||
case JCS_CMYK:
|
||||
stride = 4 * width;
|
||||
data = g_try_malloc_n (stride, height);
|
||||
format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
break;
|
||||
default:
|
||||
g_set_error (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_UNSUPPORTED_CONTENT,
|
||||
_("Unsupported JPEG colorspace (%d)"), info.out_color_space);
|
||||
jpeg_destroy_decompress (&info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!data)
|
||||
{
|
||||
g_set_error (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_TOO_LARGE,
|
||||
_("Not enough memory for image size %ux%u"), width, height);
|
||||
jpeg_destroy_decompress (&info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (info.output_scanline < info.output_height)
|
||||
{
|
||||
row[0] = (unsigned char *)(&data[stride * info.output_scanline]);
|
||||
jpeg_read_scanlines (&info, row, 1);
|
||||
}
|
||||
|
||||
switch ((int)info.out_color_space)
|
||||
{
|
||||
case JCS_GRAYSCALE:
|
||||
convert_grayscale_to_rgb (data, width, height, stride);
|
||||
format = GDK_MEMORY_R8G8B8;
|
||||
break;
|
||||
case JCS_RGB:
|
||||
break;
|
||||
case JCS_CMYK:
|
||||
convert_cmyk_to_rgba (data, width, height, stride);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
jpeg_finish_decompress (&info);
|
||||
jpeg_destroy_decompress (&info);
|
||||
|
||||
bytes = g_bytes_new_take (data, stride * height);
|
||||
|
||||
texture = gdk_memory_texture_new (width, height,
|
||||
format,
|
||||
bytes, stride);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
gdk_profiler_end_mark (before, "jpeg load", NULL);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
GBytes *
|
||||
gdk_save_jpeg (GdkTexture *texture)
|
||||
{
|
||||
struct jpeg_compress_struct info;
|
||||
struct error_handler_data jerr;
|
||||
struct jpeg_error_mgr err;
|
||||
guchar *data = NULL;
|
||||
gulong size = 0;
|
||||
guchar *input = NULL;
|
||||
guchar *row;
|
||||
int width, height, stride;
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
info.err = jpeg_std_error (&jerr.pub);
|
||||
jerr.pub.error_exit = fatal_error_handler;
|
||||
jerr.pub.output_message = output_message_handler;
|
||||
jerr.error = NULL;
|
||||
|
||||
if (sigsetjmp (jerr.setjmp_buffer, 1))
|
||||
{
|
||||
free (data);
|
||||
g_free (input);
|
||||
jpeg_destroy_compress (&info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info.err = jpeg_std_error (&err);
|
||||
jpeg_create_compress (&info);
|
||||
info.image_width = width;
|
||||
info.image_height = height;
|
||||
info.input_components = 3;
|
||||
info.in_color_space = JCS_RGB;
|
||||
|
||||
jpeg_set_defaults (&info);
|
||||
jpeg_set_quality (&info, 75, TRUE);
|
||||
|
||||
jpeg_mem_dest (&info, &data, &size);
|
||||
|
||||
stride = width * 4;
|
||||
input = g_malloc (stride * height);
|
||||
gdk_texture_download (texture, input, stride);
|
||||
convert_rgba_to_rgb (data, width, height, stride);
|
||||
|
||||
jpeg_start_compress (&info, TRUE);
|
||||
|
||||
while (info.next_scanline < info.image_height)
|
||||
{
|
||||
row = &input[info.next_scanline * stride];
|
||||
jpeg_write_scanlines (&info, &row, 1);
|
||||
}
|
||||
|
||||
jpeg_finish_compress (&info);
|
||||
|
||||
g_free (input);
|
||||
jpeg_destroy_compress (&info);
|
||||
|
||||
return g_bytes_new_with_free_func (data, size, (GDestroyNotify) free, NULL);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
43
gdk/loaders/gdkjpegprivate.h
Normal file
43
gdk/loaders/gdkjpegprivate.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2021 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_JPEG_PRIVATE_H__
|
||||
#define __GDK_JPEG_PRIVATE_H__
|
||||
|
||||
#include "gdkmemorytexture.h"
|
||||
#include <gio/gio.h>
|
||||
|
||||
#define JPEG_SIGNATURE "\xff\xd8"
|
||||
|
||||
GdkTexture *gdk_load_jpeg (GBytes *bytes,
|
||||
GError **error);
|
||||
|
||||
GBytes *gdk_save_jpeg (GdkTexture *texture);
|
||||
|
||||
static inline gboolean
|
||||
gdk_is_jpeg (GBytes *bytes)
|
||||
{
|
||||
const char *data;
|
||||
gsize size;
|
||||
|
||||
data = g_bytes_get_data (bytes, &size);
|
||||
|
||||
return size > strlen (JPEG_SIGNATURE) &&
|
||||
memcmp (data, JPEG_SIGNATURE, strlen (JPEG_SIGNATURE)) == 0;
|
||||
}
|
||||
|
||||
#endif
|
577
gdk/loaders/gdkpng.c
Normal file
577
gdk/loaders/gdkpng.c
Normal file
@@ -0,0 +1,577 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2021 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkpngprivate.h"
|
||||
|
||||
#include "gdkintl.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
#include "gdktexture.h"
|
||||
#include "gdktextureprivate.h"
|
||||
#include "gsk/ngl/fp16private.h"
|
||||
#include <png.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* The main difference between the png load/save code here and
|
||||
* gdk-pixbuf is that we can support loading 16-bit data in the
|
||||
* future, and we can extract gamma and colorspace information
|
||||
* to produce linear, color-corrected data.
|
||||
*/
|
||||
|
||||
/* {{{ Callbacks */
|
||||
|
||||
/* No sigsetjmp on Windows */
|
||||
#ifndef HAVE_SIGSETJMP
|
||||
#define sigjmp_buf jmp_buf
|
||||
#define sigsetjmp(jb, x) setjmp(jb)
|
||||
#define siglongjmp longjmp
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guchar *data;
|
||||
gsize size;
|
||||
gsize position;
|
||||
} png_io;
|
||||
|
||||
|
||||
static void
|
||||
png_read_func (png_structp png,
|
||||
png_bytep data,
|
||||
png_size_t size)
|
||||
{
|
||||
png_io *io;
|
||||
|
||||
io = png_get_io_ptr (png);
|
||||
|
||||
if (io->position + size > io->size)
|
||||
png_error (png, "Read past EOF");
|
||||
|
||||
memcpy (data, io->data + io->position, size);
|
||||
io->position += size;
|
||||
}
|
||||
|
||||
static void
|
||||
png_write_func (png_structp png,
|
||||
png_bytep data,
|
||||
png_size_t size)
|
||||
{
|
||||
png_io *io;
|
||||
|
||||
io = png_get_io_ptr (png);
|
||||
|
||||
if (io->position > io->size ||
|
||||
io->size - io->position < size)
|
||||
{
|
||||
io->size = io->position + size;
|
||||
io->data = g_realloc (io->data, io->size);
|
||||
}
|
||||
|
||||
memcpy (io->data + io->position, data, size);
|
||||
io->position += size;
|
||||
}
|
||||
|
||||
static void
|
||||
png_flush_func (png_structp png)
|
||||
{
|
||||
}
|
||||
|
||||
static png_voidp
|
||||
png_malloc_callback (png_structp o,
|
||||
png_size_t size)
|
||||
{
|
||||
return g_try_malloc (size);
|
||||
}
|
||||
|
||||
static void
|
||||
png_free_callback (png_structp o,
|
||||
png_voidp x)
|
||||
{
|
||||
g_free (x);
|
||||
}
|
||||
|
||||
static void
|
||||
png_simple_error_callback (png_structp png,
|
||||
png_const_charp error_msg)
|
||||
{
|
||||
GError **error = png_get_error_ptr (png);
|
||||
|
||||
if (error && !*error)
|
||||
g_set_error (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_CORRUPT_IMAGE,
|
||||
_("Error reading png (%s)"), error_msg);
|
||||
|
||||
longjmp (png_jmpbuf (png), 1);
|
||||
}
|
||||
|
||||
static void
|
||||
png_simple_warning_callback (png_structp png,
|
||||
png_const_charp error_msg)
|
||||
{
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Format conversion */
|
||||
|
||||
static void
|
||||
unpremultiply (guchar *data,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
gsize x, y;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
guchar *b = &data[x * 4];
|
||||
guint32 pixel;
|
||||
guchar alpha;
|
||||
|
||||
memcpy (&pixel, b, sizeof (guint32));
|
||||
alpha = (pixel & 0xff000000) >> 24;
|
||||
if (alpha == 0)
|
||||
{
|
||||
b[0] = 0;
|
||||
b[1] = 0;
|
||||
b[2] = 0;
|
||||
b[3] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
b[0] = (((pixel & 0x00ff0000) >> 16) * 255 + alpha / 2) / alpha;
|
||||
b[1] = (((pixel & 0x0000ff00) >> 8) * 255 + alpha / 2) / alpha;
|
||||
b[2] = (((pixel & 0x000000ff) >> 0) * 255 + alpha / 2) / alpha;
|
||||
b[3] = alpha;
|
||||
}
|
||||
}
|
||||
data += width * 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unpremultiply_float_to_16bit (guchar *data,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
gsize x, y;
|
||||
float *src = (float *)data;;
|
||||
guint16 *dest = (guint16 *)data;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
float r, g, b, a;
|
||||
|
||||
r = src[0];
|
||||
g = src[1];
|
||||
b = src[2];
|
||||
a = src[3];
|
||||
if (a == 0)
|
||||
{
|
||||
dest[0] = 0;
|
||||
dest[1] = 0;
|
||||
dest[2] = 0;
|
||||
dest[3] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[0] = (guint16) CLAMP (65536.f * r / a, 0.f, 65535.f);
|
||||
dest[1] = (guint16) CLAMP (65536.f * g / a, 0.f, 65535.f);
|
||||
dest[2] = (guint16) CLAMP (65536.f * b / a, 0.f, 65535.f);
|
||||
dest[3] = (guint16) CLAMP (65536.f * a, 0.f, 65535.f);
|
||||
}
|
||||
|
||||
dest += 4;
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
multiply_alpha (int alpha, int color)
|
||||
{
|
||||
int temp = (alpha * color) + 0x80;
|
||||
return ((temp + (temp >> 8)) >> 8);
|
||||
}
|
||||
|
||||
static void
|
||||
premultiply_data (png_structp png,
|
||||
png_row_infop row_info,
|
||||
png_bytep data)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < row_info->rowbytes; i += 4)
|
||||
{
|
||||
uint8_t *base = &data[i];
|
||||
uint8_t alpha = base[3];
|
||||
uint32_t p;
|
||||
|
||||
if (alpha == 0)
|
||||
{
|
||||
p = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t red = base[0];
|
||||
uint8_t green = base[1];
|
||||
uint8_t blue = base[2];
|
||||
|
||||
if (alpha != 0xff)
|
||||
{
|
||||
red = multiply_alpha (alpha, red);
|
||||
green = multiply_alpha (alpha, green);
|
||||
blue = multiply_alpha (alpha, blue);
|
||||
}
|
||||
p = ((uint32_t)alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
|
||||
}
|
||||
memcpy (base, &p, sizeof (uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
convert_bytes_to_data (png_structp png,
|
||||
png_row_infop row_info,
|
||||
png_bytep data)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < row_info->rowbytes; i += 4)
|
||||
{
|
||||
uint8_t *base = &data[i];
|
||||
uint8_t red = base[0];
|
||||
uint8_t green = base[1];
|
||||
uint8_t blue = base[2];
|
||||
uint32_t pixel;
|
||||
|
||||
pixel = (0xffu << 24) | (red << 16) | (green << 8) | (blue << 0);
|
||||
memcpy (base, &pixel, sizeof (uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
premultiply_16bit (guchar *data,
|
||||
int width,
|
||||
int height,
|
||||
int stride)
|
||||
{
|
||||
gsize x, y;
|
||||
guint16 *src;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
src = (guint16 *)data;
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
float alpha = src[x * 4 + 3] / 65535.f;
|
||||
src[x * 4 ] = (guint16) CLAMP (src[x * 4 ] * alpha, 0.f, 65535.f);
|
||||
src[x * 4 + 1] = (guint16) CLAMP (src[x * 4 + 1] * alpha, 0.f, 65535.f);
|
||||
src[x * 4 + 2] = (guint16) CLAMP (src[x * 4 + 2] * alpha, 0.f, 65535.f);
|
||||
}
|
||||
|
||||
data += stride;
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
|
||||
GdkTexture *
|
||||
gdk_load_png (GBytes *bytes,
|
||||
GError **error)
|
||||
{
|
||||
png_io io;
|
||||
png_struct *png = NULL;
|
||||
png_info *info;
|
||||
guint width, height;
|
||||
int depth, color_type;
|
||||
int interlace, stride;
|
||||
GdkMemoryFormat format;
|
||||
guchar *buffer = NULL;
|
||||
guchar **row_pointers = NULL;
|
||||
GBytes *out_bytes;
|
||||
GdkTexture *texture;
|
||||
int bpp;
|
||||
G_GNUC_UNUSED gint64 before = GDK_PROFILER_CURRENT_TIME;
|
||||
|
||||
io.data = (guchar *)g_bytes_get_data (bytes, &io.size);
|
||||
io.position = 0;
|
||||
|
||||
png = png_create_read_struct_2 (PNG_LIBPNG_VER_STRING,
|
||||
error,
|
||||
png_simple_error_callback,
|
||||
png_simple_warning_callback,
|
||||
NULL,
|
||||
png_malloc_callback,
|
||||
png_free_callback);
|
||||
if (png == NULL)
|
||||
g_error ("Out of memory");
|
||||
|
||||
info = png_create_info_struct (png);
|
||||
if (info == NULL)
|
||||
g_error ("Out of memory");
|
||||
|
||||
png_set_read_fn (png, &io, png_read_func);
|
||||
|
||||
if (sigsetjmp (png_jmpbuf (png), 1))
|
||||
{
|
||||
g_free (buffer);
|
||||
g_free (row_pointers);
|
||||
png_destroy_read_struct (&png, &info, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
png_read_info (png, info);
|
||||
|
||||
png_get_IHDR (png, info,
|
||||
&width, &height, &depth,
|
||||
&color_type, &interlace, NULL, NULL);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_palette_to_rgb (png);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY)
|
||||
png_set_expand_gray_1_2_4_to_8 (png);
|
||||
|
||||
if (png_get_valid (png, info, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha (png);
|
||||
|
||||
if (depth == 8)
|
||||
png_set_filler (png, 0xff, PNG_FILLER_AFTER);
|
||||
|
||||
if (depth < 8)
|
||||
png_set_packing (png);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb (png);
|
||||
|
||||
if (interlace != PNG_INTERLACE_NONE)
|
||||
png_set_interlace_handling (png);
|
||||
|
||||
png_read_update_info (png, info);
|
||||
png_get_IHDR (png, info,
|
||||
&width, &height, &depth,
|
||||
&color_type, &interlace, NULL, NULL);
|
||||
if ((depth != 8 && depth != 16) ||
|
||||
!(color_type == PNG_COLOR_TYPE_RGB ||
|
||||
color_type == PNG_COLOR_TYPE_RGB_ALPHA))
|
||||
{
|
||||
png_destroy_read_struct (&png, &info, NULL);
|
||||
g_set_error (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_UNSUPPORTED_CONTENT,
|
||||
_("Failed to parse png image"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (color_type)
|
||||
{
|
||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||
if (depth == 8)
|
||||
{
|
||||
format = GDK_MEMORY_DEFAULT;
|
||||
png_set_read_user_transform_fn (png, premultiply_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
png_set_swap (png);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
if (depth == 8)
|
||||
{
|
||||
format = GDK_MEMORY_DEFAULT;
|
||||
png_set_read_user_transform_fn (png, convert_bytes_to_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
format = GDK_MEMORY_R16G16B16;
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
png_set_swap (png);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (format);
|
||||
stride = width * bpp;
|
||||
if (stride % 8)
|
||||
stride += 8 - stride % 8;
|
||||
|
||||
buffer = g_try_malloc_n (height, stride);
|
||||
row_pointers = g_try_malloc_n (height, sizeof (char *));
|
||||
|
||||
if (!buffer || !row_pointers)
|
||||
{
|
||||
g_free (buffer);
|
||||
g_free (row_pointers);
|
||||
png_destroy_read_struct (&png, &info, NULL);
|
||||
g_set_error (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_TOO_LARGE,
|
||||
_("Not enough memory for image size %ux%u"), width, height);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < height; i++)
|
||||
row_pointers[i] = &buffer[i * stride];
|
||||
|
||||
png_read_image (png, row_pointers);
|
||||
png_read_end (png, info);
|
||||
|
||||
if (format == GDK_MEMORY_R16G16B16A16_PREMULTIPLIED)
|
||||
premultiply_16bit (buffer, width, height, stride);
|
||||
|
||||
out_bytes = g_bytes_new_take (buffer, height * stride);
|
||||
texture = gdk_memory_texture_new (width, height, format, out_bytes, stride);
|
||||
g_bytes_unref (out_bytes);
|
||||
|
||||
g_free (row_pointers);
|
||||
png_destroy_read_struct (&png, &info, NULL);
|
||||
|
||||
if (GDK_PROFILER_IS_RUNNING)
|
||||
{
|
||||
gint64 end = GDK_PROFILER_CURRENT_TIME;
|
||||
if (end - before > 500000)
|
||||
gdk_profiler_add_mark (before, end - before, "png load", NULL);
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
GBytes *
|
||||
gdk_save_png (GdkTexture *texture)
|
||||
{
|
||||
png_struct *png = NULL;
|
||||
png_info *info;
|
||||
png_io io = { NULL, 0, 0 };
|
||||
guint width, height, stride;
|
||||
guchar *data = NULL;
|
||||
guchar *row;
|
||||
int y;
|
||||
GdkTexture *mtexture;
|
||||
GdkMemoryFormat format;
|
||||
int png_format;
|
||||
int depth;
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
mtexture = gdk_texture_download_texture (texture);
|
||||
format = gdk_memory_texture_get_format (GDK_MEMORY_TEXTURE (mtexture));
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
stride = width * 4;
|
||||
data = g_malloc_n (stride, height);
|
||||
gdk_texture_download (mtexture, data, stride);
|
||||
unpremultiply (data, width, height);
|
||||
|
||||
png_format = PNG_COLOR_TYPE_RGB_ALPHA;
|
||||
depth = 8;
|
||||
break;
|
||||
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
data = g_malloc_n (width * 16, height);
|
||||
gdk_texture_download_float (mtexture, (float *)data, width * 4);
|
||||
unpremultiply_float_to_16bit (data, width, height);
|
||||
|
||||
png_format = PNG_COLOR_TYPE_RGB_ALPHA;
|
||||
stride = width * 8;
|
||||
depth = 16;
|
||||
break;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
png = png_create_write_struct_2 (PNG_LIBPNG_VER_STRING, NULL,
|
||||
png_simple_error_callback,
|
||||
png_simple_warning_callback,
|
||||
NULL,
|
||||
png_malloc_callback,
|
||||
png_free_callback);
|
||||
if (!png)
|
||||
return NULL;
|
||||
|
||||
info = png_create_info_struct (png);
|
||||
if (!info)
|
||||
{
|
||||
png_destroy_read_struct (&png, NULL, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sigsetjmp (png_jmpbuf (png), 1))
|
||||
{
|
||||
g_free (data);
|
||||
g_free (io.data);
|
||||
png_destroy_read_struct (&png, &info, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
png_set_write_fn (png, &io, png_write_func, png_flush_func);
|
||||
|
||||
png_set_IHDR (png, info, width, height, depth,
|
||||
png_format,
|
||||
PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_DEFAULT,
|
||||
PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
png_write_info (png, info);
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
png_set_swap (png);
|
||||
#endif
|
||||
|
||||
for (y = 0, row = data; y < height; y++, row += stride)
|
||||
png_write_rows (png, &row, 1);
|
||||
|
||||
png_write_end (png, info);
|
||||
|
||||
png_destroy_write_struct (&png, &info);
|
||||
|
||||
g_free (data);
|
||||
|
||||
return g_bytes_new_take (io.data, io.size);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
43
gdk/loaders/gdkpngprivate.h
Normal file
43
gdk/loaders/gdkpngprivate.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2021 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_PNG_PRIVATE_H__
|
||||
#define __GDK_PNG_PRIVATE_H__
|
||||
|
||||
#include "gdktexture.h"
|
||||
#include <gio/gio.h>
|
||||
|
||||
#define PNG_SIGNATURE "\x89PNG"
|
||||
|
||||
GdkTexture *gdk_load_png (GBytes *bytes,
|
||||
GError **error);
|
||||
|
||||
GBytes *gdk_save_png (GdkTexture *texture);
|
||||
|
||||
static inline gboolean
|
||||
gdk_is_png (GBytes *bytes)
|
||||
{
|
||||
const char *data;
|
||||
gsize size;
|
||||
|
||||
data = g_bytes_get_data (bytes, &size);
|
||||
|
||||
return size > strlen (PNG_SIGNATURE) &&
|
||||
memcmp (data, PNG_SIGNATURE, strlen (PNG_SIGNATURE)) == 0;
|
||||
}
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user