rays 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/rays/bitmap.cpp +28 -8
  3. data/.doc/ext/rays/bounds.cpp +1 -1
  4. data/.doc/ext/rays/camera.cpp +5 -5
  5. data/.doc/ext/rays/color.cpp +1 -1
  6. data/.doc/ext/rays/color_space.cpp +10 -6
  7. data/.doc/ext/rays/font.cpp +116 -18
  8. data/.doc/ext/rays/image.cpp +27 -4
  9. data/.doc/ext/rays/matrix.cpp +1 -1
  10. data/.doc/ext/rays/painter.cpp +5 -5
  11. data/.doc/ext/rays/point.cpp +1 -1
  12. data/.doc/ext/rays/polygon.cpp +4 -4
  13. data/.doc/ext/rays/polyline.cpp +2 -2
  14. data/.doc/ext/rays/shader.cpp +2 -2
  15. data/.github/workflows/release-gem.yml +2 -49
  16. data/.github/workflows/tag.yml +5 -28
  17. data/.github/workflows/test.yml +1 -37
  18. data/ChangeLog.md +21 -0
  19. data/Gemfile.lock +13 -8
  20. data/Rakefile +2 -2
  21. data/VERSION +1 -1
  22. data/ext/rays/bitmap.cpp +28 -8
  23. data/ext/rays/bounds.cpp +1 -1
  24. data/ext/rays/camera.cpp +5 -5
  25. data/ext/rays/color.cpp +1 -1
  26. data/ext/rays/color_space.cpp +10 -6
  27. data/ext/rays/defs.h +3 -3
  28. data/ext/rays/extconf.rb +6 -5
  29. data/ext/rays/font.cpp +120 -18
  30. data/ext/rays/image.cpp +27 -4
  31. data/ext/rays/matrix.cpp +1 -1
  32. data/ext/rays/painter.cpp +5 -5
  33. data/ext/rays/point.cpp +1 -1
  34. data/ext/rays/polygon.cpp +4 -4
  35. data/ext/rays/polyline.cpp +2 -2
  36. data/ext/rays/shader.cpp +2 -2
  37. data/include/rays/bitmap.h +2 -0
  38. data/include/rays/font.h +46 -4
  39. data/include/rays/image.h +9 -5
  40. data/include/rays/painter.h +3 -1
  41. data/include/rays/ruby/color_space.h +2 -0
  42. data/include/rays/shader.h +3 -0
  43. data/lib/rays/font.rb +4 -1
  44. data/lib/rays/image.rb +2 -0
  45. data/lib/rays/painter.rb +5 -5
  46. data/rays.gemspec +3 -3
  47. data/src/bitmap.cpp +107 -0
  48. data/src/color.cpp +17 -0
  49. data/src/font.cpp +121 -25
  50. data/src/font.h +7 -5
  51. data/src/image.cpp +102 -100
  52. data/src/ios/font.mm +77 -24
  53. data/src/opengl/color_space.cpp +4 -1
  54. data/src/opengl/painter.cpp +86 -18
  55. data/src/opengl/shader.cpp +15 -13
  56. data/src/opengl/texture.cpp +2 -2
  57. data/src/opengl/win32/opengl.cpp +17 -12
  58. data/src/osx/font.mm +77 -24
  59. data/src/painter.cpp +12 -12
  60. data/src/painter.h +5 -1
  61. data/src/polygon.cpp +21 -21
  62. data/src/polyline.cpp +4 -4
  63. data/src/sdl/bitmap.cpp +16 -10
  64. data/src/sdl/font.cpp +56 -50
  65. data/src/win32/bitmap.cpp +22 -13
  66. data/src/win32/font.cpp +43 -44
  67. data/src/win32/gdi.cpp +43 -46
  68. data/src/win32/gdi.h +6 -1
  69. data/src/win32/rays.cpp +18 -1
  70. data/test/test_bitmap.rb +28 -10
  71. data/test/test_font.rb +58 -0
  72. data/test/test_image.rb +29 -6
  73. data/test/test_painter.rb +39 -0
  74. metadata +8 -8
  75. data/.github/workflows/utils.rb +0 -127
data/src/ios/font.mm CHANGED
@@ -5,6 +5,7 @@
5
5
  #include <memory>
6
6
  #import <CoreGraphics/CGContext.h>
7
7
  #import <CoreText/CoreText.h>
8
+ #import <UIKit/UIKit.h>
8
9
  #include <xot/string.h>
9
10
  #include <xot/util.h>
10
11
  #include "rays/exception.h"
@@ -18,6 +19,8 @@ namespace Rays
18
19
 
19
20
  typedef std::shared_ptr<const __CFAttributedString> CFAttributedStringPtr;
20
21
 
22
+ typedef std::shared_ptr<const __CTFontDescriptor> CTFontDescriptorPtr;
23
+
21
24
  typedef std::shared_ptr<CGDataProvider> CGDataProviderPtr;
22
25
 
23
26
  typedef std::shared_ptr<CGFont> CGFontPtr;
@@ -30,8 +33,6 @@ namespace Rays
30
33
 
31
34
  CTFontRef font = NULL;
32
35
 
33
- String path;
34
-
35
36
  ~Data ()
36
37
  {
37
38
  if (font)
@@ -44,6 +45,63 @@ namespace Rays
44
45
  };// RawFont::Data
45
46
 
46
47
 
48
+ static const struct {int weight; CGFloat native;} NATIVE_WEIGHTS[] =
49
+ {
50
+ {Font::WEIGHT_MIN, -1.0},
51
+ {Font::WEIGHT_THIN, UIFontWeightUltraLight},
52
+ {Font::WEIGHT_EXTRALIGHT, UIFontWeightThin},
53
+ {Font::WEIGHT_LIGHT, UIFontWeightLight},
54
+ {Font::WEIGHT_NORMAL, UIFontWeightRegular},
55
+ {Font::WEIGHT_MEDIUM, UIFontWeightMedium},
56
+ {Font::WEIGHT_SEMIBOLD, UIFontWeightSemibold},
57
+ {Font::WEIGHT_BOLD, UIFontWeightBold},
58
+ {Font::WEIGHT_EXTRABOLD, UIFontWeightHeavy},
59
+ {Font::WEIGHT_BLACK, UIFontWeightBlack},
60
+ {Font::WEIGHT_MAX, 1.0}
61
+ };
62
+
63
+ static CGFloat
64
+ to_native_weight (int weight)
65
+ {
66
+ size_t last = sizeof(NATIVE_WEIGHTS) / sizeof(NATIVE_WEIGHTS[0]) - 1;
67
+ for (size_t i = 1; i <= last; ++i)
68
+ {
69
+ if (weight > NATIVE_WEIGHTS[i].weight) continue;
70
+
71
+ const auto& lo = NATIVE_WEIGHTS[i - 1];
72
+ const auto& hi = NATIVE_WEIGHTS[i];
73
+ CGFloat t = (CGFloat) (weight - lo.weight) / (hi.weight - lo.weight);
74
+ return lo.native + (hi.native - lo.native) * t;
75
+ }
76
+ return NATIVE_WEIGHTS[last].native;
77
+ }
78
+
79
+ static CTFontRef
80
+ create_styled_font (CTFontRef base, coord size, int weight, bool italic)
81
+ {
82
+ Xot::CFStringPtr family(CTFontCopyFamilyName(base), Xot::safe_cfrelease);
83
+ if (!family) return NULL;
84
+
85
+ NSDictionary* traits =
86
+ @{
87
+ (id) kCTFontWeightTrait: @(to_native_weight(weight)),
88
+ (id) kCTFontSymbolicTrait: @(italic ? kCTFontTraitItalic : 0)
89
+ };
90
+ NSDictionary* attributes =
91
+ @{
92
+ (id) kCTFontFamilyNameAttribute: (__bridge NSString*) family.get(),
93
+ (id) kCTFontTraitsAttribute: traits
94
+ };
95
+
96
+ CTFontDescriptorPtr descriptor(
97
+ CTFontDescriptorCreateWithAttributes((__bridge CFDictionaryRef) attributes),
98
+ Xot::safe_cfrelease);
99
+ if (!descriptor) return NULL;
100
+
101
+ return CTFontCreateWithFontDescriptor(descriptor.get(), size, NULL);
102
+ }
103
+
104
+
47
105
  static CTLinePtr
48
106
  make_line (CTFontRef font, const char* str)
49
107
  {
@@ -64,15 +122,15 @@ namespace Rays
64
122
  CFDictionaryCreate(
65
123
  NULL, (const void**) &keys, (const void**) &values, nkeys,
66
124
  &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks),
67
- CFRelease);
125
+ Xot::safe_cfrelease);
68
126
 
69
127
  CFAttributedStringPtr attrstr(
70
128
  CFAttributedStringCreate(NULL, Xot::String(str).to_cfstr().get(), attr.get()),
71
- CFRelease);
129
+ Xot::safe_cfrelease);
72
130
 
73
131
  return CTLinePtr(
74
132
  CTLineCreateWithAttributedString(attrstr.get()),
75
- CFRelease);
133
+ Xot::safe_cfrelease);
76
134
  }
77
135
 
78
136
  const FontFamilyMap&
@@ -117,7 +175,6 @@ namespace Rays
117
175
 
118
176
  RawFont rawfont;
119
177
  rawfont.self->font = ctfont;
120
- rawfont.self->path = path;
121
178
  return rawfont;
122
179
  }
123
180
 
@@ -126,20 +183,23 @@ namespace Rays
126
183
  {
127
184
  }
128
185
 
129
- RawFont::RawFont (const char* name, coord size)
186
+ RawFont::RawFont (const char* name, coord size, int weight, bool italic)
130
187
  {
131
- self->font = name
188
+ CTFontRef font = name
132
189
  ? CTFontCreateWithName(Xot::String(name).to_cfstr().get(), size, NULL)
133
190
  : CTFontCreateUIFontForLanguage(kCTFontSystemFontType, size, NULL);
134
- }
135
191
 
136
- RawFont::RawFont (const This& obj, coord size)
137
- {
138
- const char* path = obj.self->path.empty() ? NULL : obj.self->path.c_str();
139
- if (path)
140
- *this = RawFont_load(path, size);
141
- else
142
- self->font = CTFontCreateWithName(obj.name().to_cfstr().get(), size, NULL);
192
+ if (font && (weight != Font::WEIGHT_NORMAL || italic))
193
+ {
194
+ CTFontRef styled = create_styled_font(font, size, weight, italic);
195
+ if (styled)
196
+ {
197
+ CFRelease(font);
198
+ font = styled;
199
+ }
200
+ }
201
+
202
+ self->font = font;
143
203
  }
144
204
 
145
205
  RawFont::~RawFont ()
@@ -190,17 +250,10 @@ namespace Rays
190
250
  {
191
251
  if (!*this) return "";
192
252
 
193
- Xot::CFStringPtr str(CTFontCopyFullName(self->font), CFRelease);
253
+ Xot::CFStringPtr str(CTFontCopyFullName(self->font), Xot::safe_cfrelease);
194
254
  return Xot::to_s(str);
195
255
  }
196
256
 
197
- coord
198
- RawFont::size () const
199
- {
200
- if (!*this) return 0;
201
- return CTFontGetSize(self->font);
202
- }
203
-
204
257
  coord
205
258
  RawFont::get_width (const char* str) const
206
259
  {
@@ -30,7 +30,10 @@ namespace Rays
30
30
  if (format)
31
31
  {
32
32
  if (cs.is_rgb()) *format = cs.has_alpha() ? GL_RGBA : GL_RGB;
33
- #ifndef IOS
33
+ #ifdef IOS
34
+ else if (cs.is_bgr() && cs.has_alpha())
35
+ *format = GL_BGRA_EXT;
36
+ #else
34
37
  else if (cs.is_bgr()) *format = cs.has_alpha() ? GL_BGRA : GL_BGR;
35
38
  #endif
36
39
  else if (cs.is_gray()) *format = GL_LUMINANCE;
@@ -132,7 +132,7 @@ namespace Rays
132
132
 
133
133
  const uint* get () const
134
134
  {
135
- return &indices[0];
135
+ return indices.data();
136
136
  }
137
137
 
138
138
  private:
@@ -249,7 +249,7 @@ namespace Rays
249
249
 
250
250
  if (!buffers.empty())
251
251
  {
252
- glDeleteBuffers((GLsizei) buffers.size(), &buffers[0]);
252
+ glDeleteBuffers((GLsizei) buffers.size(), buffers.data());
253
253
  OpenGL_check_error(__FILE__, __LINE__);
254
254
  }
255
255
 
@@ -259,53 +259,75 @@ namespace Rays
259
259
 
260
260
  void apply_blend_mode ()
261
261
  {
262
+ // sources arrive premultiplied (see rays/shader.h), so the source color
263
+ // is never scaled by GL_SRC_ALPHA here, and alpha always accumulates
264
+ // as a union: a = a_src + a_dst * (1 - a_src)
265
+
262
266
  switch (state.blend_mode)
263
267
  {
264
268
  case BLEND_NORMAL:
265
269
  glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
266
270
  glBlendFuncSeparate(
267
- GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
271
+ GL_ONE, GL_ONE_MINUS_SRC_ALPHA,
272
+ GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
268
273
  break;
269
274
 
270
275
  case BLEND_ADD:
271
276
  glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
272
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
277
+ glBlendFuncSeparate(
278
+ GL_ONE, GL_ONE,
279
+ GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
273
280
  break;
274
281
 
275
282
  case BLEND_SUBTRACT:
276
283
  glBlendEquationSeparate(GL_FUNC_REVERSE_SUBTRACT, GL_FUNC_ADD);
277
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
284
+ glBlendFuncSeparate(
285
+ GL_ONE, GL_ONE,
286
+ GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
278
287
  break;
279
288
 
280
289
  case BLEND_LIGHTEST:
281
290
  glBlendEquationSeparate(GL_MAX, GL_FUNC_ADD);
282
- glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
291
+ glBlendFuncSeparate(
292
+ GL_ONE, GL_ONE,
293
+ GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
283
294
  break;
284
295
 
285
296
  case BLEND_DARKEST:
286
297
  glBlendEquationSeparate(GL_MIN, GL_FUNC_ADD);
287
- glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
298
+ glBlendFuncSeparate(
299
+ GL_ONE, GL_ONE,
300
+ GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
288
301
  break;
289
302
 
290
303
  case BLEND_EXCLUSION:
291
304
  glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
292
305
  glBlendFuncSeparate(
293
- GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE);
306
+ GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR,
307
+ GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
294
308
  break;
295
309
 
296
310
  case BLEND_MULTIPLY:
311
+ // assumes an opaque destination; the Cs * (1 - Ad) term of the
312
+ // exact formula is not expressible with fixed-function blending
297
313
  glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
298
- glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ONE, GL_ONE);
314
+ glBlendFuncSeparate(
315
+ GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA,
316
+ GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
299
317
  break;
300
318
 
301
319
  case BLEND_SCREEN:
302
320
  glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
303
- glBlendFuncSeparate(GL_ONE_MINUS_DST_COLOR, GL_ONE, GL_ONE, GL_ONE);
321
+ glBlendFuncSeparate(
322
+ GL_ONE, GL_ONE_MINUS_SRC_COLOR,
323
+ GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
304
324
  break;
305
325
 
306
326
  case BLEND_REPLACE:
307
327
  glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
308
- glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO);
328
+ glBlendFuncSeparate(
329
+ GL_ONE, GL_ZERO,
330
+ GL_ONE, GL_ZERO);
309
331
  break;
310
332
 
311
333
  default:
@@ -489,7 +511,7 @@ namespace Rays
489
511
  std::vector<Color> colors_(npoints, *color);
490
512
  apply_attribute(
491
513
  self, program, names.attribute_color_names,
492
- (const Coord4*) &colors_[0], npoints);
514
+ (const Coord4*) colors_.data(), npoints);
493
515
  #else
494
516
  for (const auto& name : names.attribute_color_names)
495
517
  {
@@ -841,6 +863,12 @@ namespace Rays
841
863
  if (!self->is_painting())
842
864
  invalid_state_error(__FILE__, __LINE__, "'painting' should be true.");
843
865
 
866
+ if (Xot::check_and_remove_flag(&self->flags, Painter::Data::CLEAR_DEPTH))
867
+ {
868
+ glClear(GL_DEPTH_BUFFER_BIT);
869
+ OpenGL_check_error(__FILE__, __LINE__);
870
+ }
871
+
844
872
  std::unique_ptr<TextureInfo> ptexinfo;
845
873
  texinfo = setup_texinfo(self, texinfo, &ptexinfo);
846
874
  shader = setup_shader(self, shader, texinfo);
@@ -862,8 +890,9 @@ namespace Rays
862
890
  if (!setup_triangle_fan_indices(&fan_indices, npoints))
863
891
  return;
864
892
  batch(
865
- painter, MODE_TRIANGLES, color, points, npoints, &fan_indices[0], fan_indices.size(),
866
- colors, texcoords, texinfo, *shader);
893
+ painter, MODE_TRIANGLES, color, points, npoints,
894
+ fan_indices.data(), fan_indices.size(), colors, texcoords,
895
+ texinfo, *shader);
867
896
  }
868
897
  else
869
898
  {
@@ -953,6 +982,13 @@ namespace Rays
953
982
  if (width == 0) width = str_w;
954
983
  if (height == 0) height = str_h;
955
984
 
985
+ // the baseline where Font's ascent tells, of the font at density 1:
986
+ // the font drawn at density may round its ascent apart from it
987
+ coord ascent = 0, ascent_drawn = 0;
988
+ font.get_height(&ascent);
989
+ rawfont.get_height(&ascent_drawn);
990
+ y += ascent - ascent_drawn / density;
991
+
956
992
  Painter_draw_image(
957
993
  painter, self->text_image,
958
994
  0, 0, str_w, str_h,
@@ -962,6 +998,39 @@ namespace Rays
962
998
  debug_draw_text_line(painter, font, x, y, str_w / density, str_h / density);
963
999
  }
964
1000
 
1001
+ bool
1002
+ Painter_get_pixel (Color* color, Painter* painter, coord x, coord y)
1003
+ {
1004
+ if (!color)
1005
+ argument_error(__FILE__, __LINE__);
1006
+ if (!painter)
1007
+ argument_error(__FILE__, __LINE__);
1008
+
1009
+ PainterData* self = get_data(painter);
1010
+
1011
+ const Bounds& vp = self->viewport;
1012
+ if (!vp.is_include(x, y))
1013
+ return false;
1014
+
1015
+ if (self->is_painting())
1016
+ draw_batch(self);
1017
+
1018
+ float density = self->pixel_density;
1019
+ GLint px = (GLint) ((x - vp.x) * density);
1020
+ GLint py = (GLint) ((y - vp.y) * density);
1021
+ if (!self->frame_buffer)
1022
+ py = (GLint) (vp.height * density) - 1 - py;
1023
+
1024
+ FrameBufferBinder binder(self->frame_buffer ? self->frame_buffer.id() : 0);
1025
+
1026
+ GLubyte rgba[4] = {0, 0, 0, 0};
1027
+ glReadPixels(px, py, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba);
1028
+ OpenGL_check_error(__FILE__, __LINE__);
1029
+
1030
+ color->reset8(rgba[0], rgba[1], rgba[2], rgba[3]);
1031
+ return true;
1032
+ }
1033
+
965
1034
 
966
1035
  Painter::Painter ()
967
1036
  : self(new PainterData())
@@ -1050,9 +1119,8 @@ namespace Rays
1050
1119
  self->batcher.init(self->state);
1051
1120
 
1052
1121
  Xot::remove_flag(&self->flags, Painter::Data::UNBATCHABLE_STATE_CHANGED);
1122
+ Xot:: add_flag(&self->flags, Painter::Data::CLEAR_DEPTH);
1053
1123
  Xot:: add_flag(&self->flags, Painter::Data::PAINTING);
1054
-
1055
- glClear(GL_DEPTH_BUFFER_BIT);
1056
1124
  }
1057
1125
 
1058
1126
  void
@@ -1075,7 +1143,7 @@ namespace Rays
1075
1143
  self->opengl_state.pop();
1076
1144
  self->default_indices.clear();
1077
1145
 
1078
- glFinish();
1146
+ glFlush();
1079
1147
 
1080
1148
  if (self->frame_buffer)
1081
1149
  FrameBuffer_unbind();
@@ -1092,7 +1160,7 @@ namespace Rays
1092
1160
  Painter_flush(this);
1093
1161
 
1094
1162
  const Color& c = self->state.background;
1095
- glClearColor(c.red, c.green, c.blue, c.alpha);
1163
+ glClearColor(c.red * c.alpha, c.green * c.alpha, c.blue * c.alpha, c.alpha);
1096
1164
  glClear(GL_COLOR_BUFFER_BIT);
1097
1165
  OpenGL_check_error(__FILE__, __LINE__);
1098
1166
  }
@@ -72,7 +72,7 @@ namespace Rays
72
72
  "varying vec4 " + V_COLOR + ";\n"
73
73
  "void main ()\n"
74
74
  "{\n"
75
- " gl_FragColor = " + V_COLOR + ";\n"
75
+ " gl_FragColor = vec4(" + V_COLOR + ".rgb * " + V_COLOR + ".a, " + V_COLOR + ".a);\n"
76
76
  "}\n");
77
77
  }
78
78
 
@@ -95,7 +95,8 @@ namespace Rays
95
95
  V_TEXCOORD_MIN + ".xy, " +
96
96
  V_TEXCOORD_MAX + ".xy - " + U_TEXCOORD_PIXEL + ".xy);\n"
97
97
  " vec4 _rays_color = texture2D(" + U_TEXTURE + ", _rays_texcoord);\n"
98
- " gl_FragColor = " + V_COLOR + " * _rays_color;\n"
98
+ " gl_FragColor = _rays_color *\n"
99
+ " vec4(" + V_COLOR + ".rgb * " + V_COLOR + ".a, " + V_COLOR + ".a);\n"
99
100
  "}\n");
100
101
  }
101
102
 
@@ -114,9 +115,11 @@ namespace Rays
114
115
  "{\n"
115
116
  " vec2 _rays_min = " + V_TEXCOORD_MIN + ".xy;\n"
116
117
  " vec2 _rays_len = " + V_TEXCOORD_MAX + ".xy - _rays_min;\n"
117
- " vec2 _rays_texcoord = mod(" + V_TEXCOORD + ".xy - _rays_min, _rays_len) + _rays_min;\n"
118
+ " vec2 _rays_texcoord =\n"
119
+ " mod(" + V_TEXCOORD + ".xy - _rays_min, _rays_len) + _rays_min;\n"
118
120
  " vec4 _rays_color = texture2D(" + U_TEXTURE + ", _rays_texcoord);\n"
119
- " gl_FragColor = " + V_COLOR + " * _rays_color;\n"
121
+ " gl_FragColor = _rays_color *\n"
122
+ " vec4(" + V_COLOR + ".rgb * " + V_COLOR + ".a, " + V_COLOR + ".a);\n"
120
123
  "}\n");
121
124
  }
122
125
 
@@ -131,16 +134,15 @@ namespace Rays
131
134
  "uniform sampler2D " + U_TEXTURE + ";\n"
132
135
  "void main ()\n"
133
136
  "{\n"
134
- " vec4 _rays_col = texture2D(" + U_TEXTURE + ", " + V_TEXCOORD + ".xy);\n"
135
- #if defined(OSX) || defined(IOS) || defined(LINUX)
136
- // restore premultiplied rgb values
137
- " vec3 _rays_rgb = _rays_col.a != 0.0 ? _rays_col.rgb / _rays_col.a : _rays_col.rgb;\n"
138
- " gl_FragColor = " + V_COLOR + " * vec4(_rays_rgb, _rays_col.a);\n"
139
- #elif defined(WIN32)
140
- " float _rays_a = (_rays_col.r + _rays_col.g + _rays_col.b) / 3.0;\n"
141
- " gl_FragColor = " + V_COLOR + " * vec4(1.0, 1.0, 1.0, _rays_a);\n"
137
+ " vec4 _rays_tex = texture2D(" + U_TEXTURE + ", " + V_TEXCOORD + ".xy);\n"
138
+ " vec4 _rays_col =\n"
139
+ " vec4(" + V_COLOR + ".rgb * " + V_COLOR + ".a, " + V_COLOR + ".a);\n"
140
+ #if defined(WIN32)
141
+ // GDI writes no alpha; white text on black gives the coverage
142
+ " float _rays_a = (_rays_tex.r + _rays_tex.g + _rays_tex.b) / 3.0;\n"
143
+ " gl_FragColor = _rays_col * _rays_a;\n"
142
144
  #else
143
- " gl_FragColor = " + V_COLOR + " * _rays_col;\n"
145
+ " gl_FragColor = _rays_tex * _rays_col;\n"
144
146
  #endif
145
147
  "}\n");
146
148
  }
@@ -203,7 +203,7 @@ namespace Rays
203
203
  glTexImage2D(
204
204
  GL_TEXTURE_2D, 0, internalformat, width, height, 0, format, type,
205
205
  bitmap ? bitmap->pixels() : NULL);
206
- npot = OpenGL_has_error();
206
+ npot = !OpenGL_has_error();
207
207
  }
208
208
 
209
209
  if (!npot)
@@ -213,7 +213,7 @@ namespace Rays
213
213
  int height_pow2 = min_pow2(height);
214
214
 
215
215
  glTexImage2D(
216
- GL_TEXTURE_2D, 0, format, width_pow2, height_pow2, 0, format, type,
216
+ GL_TEXTURE_2D, 0, internalformat, width_pow2, height_pow2, 0, format, type,
217
217
  bitmap ? resize_bitmap(*bitmap, width_pow2, height_pow2)->pixels() : NULL);
218
218
  OpenGL_check_error(__FILE__, __LINE__);
219
219
 
@@ -11,17 +11,18 @@ namespace Rays
11
11
  {
12
12
 
13
13
 
14
- static const char* WINDOW_CLASS = "Rays:OffscreenWindow";
14
+ static const wchar_t* WINDOW_CLASS = L"Rays:OffscreenWindow";
15
15
 
16
16
 
17
17
  const PIXELFORMATDESCRIPTOR*
18
- get_pixel_format_descriptor ()
18
+ OpenGL_get_pixel_format_descriptor ()
19
19
  {
20
20
  static const PIXELFORMATDESCRIPTOR PFD =
21
21
  {
22
22
  sizeof(PIXELFORMATDESCRIPTOR), 1,
23
- PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
24
- PFD_TYPE_RGBA, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0,
23
+ PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
24
+ PFD_DOUBLEBUFFER | PFD_SUPPORT_COMPOSITION,
25
+ PFD_TYPE_RGBA, 24, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 16, 0, 0,
25
26
  PFD_MAIN_PLANE, 0, 0, 0, 0
26
27
  };
27
28
  return &PFD;
@@ -39,26 +40,26 @@ namespace Rays
39
40
 
40
41
  OffscreenContext ()
41
42
  {
42
- WNDCLASS wc = {0};
43
- wc.lpfnWndProc = DefWindowProc;
44
- wc.hInstance = GetModuleHandle(NULL);
43
+ WNDCLASSW wc = {0};
44
+ wc.lpfnWndProc = DefWindowProcW;
45
+ wc.hInstance = GetModuleHandleW(NULL);
45
46
  wc.lpszClassName = WINDOW_CLASS;
46
47
  wc.style = CS_OWNDC;
47
- if (!RegisterClass(&wc))
48
+ if (!RegisterClassW(&wc))
48
49
  {
49
50
  // It's OK to be registered by the duplicated Rays module
50
51
  if (GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
51
52
  system_error(__FILE__, __LINE__);
52
53
  }
53
54
 
54
- hwnd = CreateWindowEx(
55
- WS_EX_LAYERED, WINDOW_CLASS, "", WS_POPUP, 0, 0, 1, 1,
56
- NULL, NULL, GetModuleHandle(NULL), NULL);
55
+ hwnd = CreateWindowExW(
56
+ WS_EX_LAYERED, WINDOW_CLASS, L"", WS_POPUP, 0, 0, 1, 1,
57
+ NULL, NULL, GetModuleHandleW(NULL), NULL);
57
58
  if (!hwnd)
58
59
  system_error(__FILE__, __LINE__);
59
60
 
60
61
  hdc = GetDC(hwnd);
61
- const auto* pfd = get_pixel_format_descriptor();
62
+ const auto* pfd = OpenGL_get_pixel_format_descriptor();
62
63
  int pf = ChoosePixelFormat(hdc, pfd);
63
64
  if (!SetPixelFormat(hdc, pf, pfd))
64
65
  system_error(__FILE__, __LINE__);
@@ -127,6 +128,10 @@ namespace Rays
127
128
  activate_offscreen_context ()
128
129
  {
129
130
  const auto* c = get_opengl_offscreen_context();
131
+
132
+ if (wglGetCurrentContext() == c->hrc)
133
+ return;
134
+
130
135
  if (!wglMakeCurrent(c->hdc, c->hrc))
131
136
  system_error(__FILE__, __LINE__);
132
137
  }