Raster packed (#5795)

* raster: use hb_packed_t for unaligned BGRA32 access

* algs: support encapsulated hb_packed_t and fix raster callsites
diff --git a/src/hb-algs.hh b/src/hb-algs.hh
index 0a7bdfc..c580496 100644
--- a/src/hb-algs.hh
+++ b/src/hb-algs.hh
@@ -89,7 +89,16 @@
 { return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
 
 template <typename Type>
-struct __attribute__((packed)) hb_packed_t { Type v; };
+struct __attribute__((packed)) hb_packed_t
+{
+  hb_packed_t () = default;
+  constexpr hb_packed_t (Type V) : v (V) {}
+  operator Type () const { return v; }
+  hb_packed_t & operator = (Type V) { v = V; return *this; }
+
+  private:
+  Type v;
+};
 
 #ifndef HB_FAST_NUM_ACCESS
 
@@ -134,9 +143,9 @@
 #if HB_FAST_NUM_ACCESS
   {
     if (BE == (__BYTE_ORDER == __BIG_ENDIAN))
-      ((hb_packed_t<uint16_t> *) v)->v = V;
+      *((hb_packed_t<uint16_t> *) v) = V;
     else
-      ((hb_packed_t<uint16_t> *) v)->v = __builtin_bswap16 (V);
+      *((hb_packed_t<uint16_t> *) v) = __builtin_bswap16 (V);
   }
 #else
     : v {BE ? uint8_t ((V >>  8) & 0xFF) : uint8_t ((V      ) & 0xFF),
@@ -147,9 +156,9 @@
   {
 #if HB_FAST_NUM_ACCESS
     return (BE == (__BYTE_ORDER == __BIG_ENDIAN)) ?
-      ((const hb_packed_t<uint16_t> *) v)->v
+      (uint16_t) *((const hb_packed_t<uint16_t> *) v)
     :
-      __builtin_bswap16 (((const hb_packed_t<uint16_t> *) v)->v)
+      __builtin_bswap16 ((uint16_t) *((const hb_packed_t<uint16_t> *) v))
     ;
 #else
     return (BE ? (v[0] <<  8) : (v[0]      ))
@@ -186,9 +195,9 @@
 #if HB_FAST_NUM_ACCESS
   {
     if (BE == (__BYTE_ORDER == __BIG_ENDIAN))
-      ((hb_packed_t<uint32_t> *) v)->v = V;
+      *((hb_packed_t<uint32_t> *) v) = V;
     else
-      ((hb_packed_t<uint32_t> *) v)->v = __builtin_bswap32 (V);
+      *((hb_packed_t<uint32_t> *) v) = __builtin_bswap32 (V);
   }
 #else
     : v {BE ? uint8_t ((V >> 24) & 0xFF) : uint8_t ((V      ) & 0xFF),
@@ -200,9 +209,9 @@
   constexpr operator Type () const {
 #if HB_FAST_NUM_ACCESS
     return (BE == (__BYTE_ORDER == __BIG_ENDIAN)) ?
-      ((const hb_packed_t<uint32_t> *) v)->v
+      (uint32_t) *((const hb_packed_t<uint32_t> *) v)
     :
-      __builtin_bswap32 (((const hb_packed_t<uint32_t> *) v)->v)
+      __builtin_bswap32 ((uint32_t) *((const hb_packed_t<uint32_t> *) v))
     ;
 #else
     return (BE ? (v[0] << 24) : (v[0]      ))
@@ -226,9 +235,9 @@
 #if HB_FAST_NUM_ACCESS
   {
     if (BE == (__BYTE_ORDER == __BIG_ENDIAN))
-      ((hb_packed_t<uint64_t> *) v)->v = V;
+      *((hb_packed_t<uint64_t> *) v) = V;
     else
-      ((hb_packed_t<uint64_t> *) v)->v = __builtin_bswap64 (V);
+      *((hb_packed_t<uint64_t> *) v) = __builtin_bswap64 (V);
   }
 #else
     : v {BE ? uint8_t ((V >> 56) & 0xFF) : uint8_t ((V      ) & 0xFF),
@@ -244,9 +253,9 @@
   constexpr operator Type () const {
 #if HB_FAST_NUM_ACCESS
     return (BE == (__BYTE_ORDER == __BIG_ENDIAN)) ?
-      ((const hb_packed_t<uint64_t> *) v)->v
+      (uint64_t) *((const hb_packed_t<uint64_t> *) v)
     :
-      __builtin_bswap64 (((const hb_packed_t<uint64_t> *) v)->v)
+      __builtin_bswap64 ((uint64_t) *((const hb_packed_t<uint64_t> *) v))
     ;
 #else
     return (BE ? (uint64_t (v[0]) << 56) : (uint64_t (v[0])      ))
@@ -276,12 +285,12 @@
   {
 #if HB_FAST_NUM_ACCESS
     {
-      if (BE == (__BYTE_ORDER == __BIG_ENDIAN))
-      {
-        ((hb_packed_t<Type> *) v)->v = V;
-        return;
-      }
-    }
+	      if (BE == (__BYTE_ORDER == __BIG_ENDIAN))
+	      {
+	        *((hb_packed_t<Type> *) v) = V;
+	        return;
+	      }
+	    }
 #endif
 
     union {
@@ -289,7 +298,7 @@
       hb_packed_t<IntType> i;
     } u = {{V}};
 
-    const HBInt<BE, IntType> I = u.i.v;
+    const HBInt<BE, IntType> I = (IntType) u.i;
     for (unsigned i = 0; i < Bytes; i++)
       v[i] = I.v[i];
   }
@@ -297,10 +306,10 @@
   /* c++14 constexpr */ operator Type () const
   {
 #if HB_FAST_NUM_ACCESS
-    {
-      if (BE == (__BYTE_ORDER == __BIG_ENDIAN))
-	return ((const hb_packed_t<Type> *) v)->v;
-    }
+	    {
+	      if (BE == (__BYTE_ORDER == __BIG_ENDIAN))
+		return (Type) *((const hb_packed_t<Type> *) v);
+	    }
 #endif
 
     HBInt<BE, IntType> I;
@@ -312,7 +321,7 @@
       hb_packed_t<Type> f;
     } u = {{I}};
 
-    return u.f.v;
+    return (Type) u.f;
   }
   private: uint8_t v[Bytes];
 };
diff --git a/src/hb-raster-image.cc b/src/hb-raster-image.cc
index aaff8c7..77c6d2b 100644
--- a/src/hb-raster-image.cc
+++ b/src/hb-raster-image.cc
@@ -396,10 +396,10 @@
 
   for (unsigned y = 0; y < h; y++)
   {
-    uint32_t *dp = reinterpret_cast<uint32_t *> (buffer.arrayZ + y * stride);
-    const uint32_t *sp = reinterpret_cast<const uint32_t *> (src->buffer.arrayZ + y * stride);
+    hb_packed_t<uint32_t> *dp = (hb_packed_t<uint32_t> *) (buffer.arrayZ + y * stride);
+    const hb_packed_t<uint32_t> *sp = (const hb_packed_t<uint32_t> *) (src->buffer.arrayZ + y * stride);
     for (unsigned x = 0; x < w; x++)
-      dp[x] = composite_pixel (sp[x], dp[x], mode);
+      dp[x] = hb_packed_t<uint32_t> (composite_pixel ((uint32_t) sp[x], (uint32_t) dp[x], mode));
   }
 }
 
diff --git a/src/hb-raster-paint.cc b/src/hb-raster-paint.cc
index b9537f5..13d1a41 100644
--- a/src/hb-raster-paint.cc
+++ b/src/hb-raster-paint.cc
@@ -563,7 +563,7 @@
   {
     for (unsigned y = clip.min_y; y < clip.max_y; y++)
     {
-      uint32_t *__restrict row = reinterpret_cast<uint32_t *> (surf->buffer.arrayZ + y * stride);
+      hb_packed_t<uint32_t> *__restrict row = (hb_packed_t<uint32_t> *) (surf->buffer.arrayZ + y * stride);
       const uint8_t *__restrict clip_row = clip.alpha.arrayZ + y * clip.stride;
       for (unsigned x = clip.min_x; x < clip.max_x; x++)
       {
@@ -572,14 +572,14 @@
 	if (clip_alpha == 255)
 	{
 	  if (premul_a == 255)
-	    row[x] = premul;
+	    row[x] = hb_packed_t<uint32_t> (premul);
 	  else
-	    row[x] = hb_raster_src_over (premul, row[x]);
+	    row[x] = hb_packed_t<uint32_t> (hb_raster_src_over (premul, (uint32_t) row[x]));
 	}
 	else
 	{
 	  uint32_t src = hb_raster_alpha_mul (premul, clip_alpha);
-	  row[x] = hb_raster_src_over (src, row[x]);
+	  row[x] = hb_packed_t<uint32_t> (hb_raster_src_over (src, (uint32_t) row[x]));
 	}
       }
     }
@@ -588,9 +588,9 @@
   {
     for (unsigned y = clip.min_y; y < clip.max_y; y++)
     {
-      uint32_t *row = reinterpret_cast<uint32_t *> (surf->buffer.arrayZ + y * stride);
+      hb_packed_t<uint32_t> *row = (hb_packed_t<uint32_t> *) (surf->buffer.arrayZ + y * stride);
       for (unsigned x = clip.min_x; x < clip.max_x; x++)
-	row[x] = hb_raster_src_over (premul, row[x]);
+	row[x] = hb_packed_t<uint32_t> (hb_raster_src_over (premul, (uint32_t) row[x]));
     }
   }
 }
@@ -653,6 +653,7 @@
   float inv_y0 = (t.yx * t.x0 - t.xx * t.y0) * inv_det;
 
   unsigned surf_stride = surf->extents.stride;
+  const hb_packed_t<uint32_t> *src_data = (const hb_packed_t<uint32_t> *) data;
   int ox = surf->extents.x_origin;
   int oy = surf->extents.y_origin;
 
@@ -666,7 +667,7 @@
   {
     for (unsigned py = clip.min_y; py < clip.max_y; py++)
     {
-      uint32_t *row = reinterpret_cast<uint32_t *> (surf->buffer.arrayZ + py * surf_stride);
+      hb_packed_t<uint32_t> *row = (hb_packed_t<uint32_t> *) (surf->buffer.arrayZ + py * surf_stride);
       float gx = inv_xx * (float) ((int) clip.min_x + ox) + inv_xy * (float) ((int) py + oy) + inv_x0;
       float gy = inv_yx * (float) ((int) clip.min_x + ox) + inv_yy * (float) ((int) py + oy) + inv_y0;
       for (unsigned px = clip.min_x; px < clip.max_x; px++)
@@ -682,8 +683,8 @@
 	  continue;
 	}
 
-	uint32_t src_px = reinterpret_cast<const uint32_t *> (data)[iy * width + ix];
-	row[px] = hb_raster_src_over (src_px, row[px]);
+	uint32_t src_px = ((uint32_t) src_data[iy * width + ix]);
+	row[px] = hb_packed_t<uint32_t> (hb_raster_src_over (src_px, (uint32_t) row[px]));
 	gx += inv_xx;
 	gy += inv_yx;
       }
@@ -693,7 +694,7 @@
   {
     for (unsigned py = clip.min_y; py < clip.max_y; py++)
     {
-      uint32_t *row = reinterpret_cast<uint32_t *> (surf->buffer.arrayZ + py * surf_stride);
+      hb_packed_t<uint32_t> *row = (hb_packed_t<uint32_t> *) (surf->buffer.arrayZ + py * surf_stride);
       const uint8_t *clip_row = clip.alpha.arrayZ + py * clip.stride;
       float gx = inv_xx * (float) ((int) clip.min_x + ox) + inv_xy * (float) ((int) py + oy) + inv_x0;
       float gy = inv_yx * (float) ((int) clip.min_x + ox) + inv_yy * (float) ((int) py + oy) + inv_y0;
@@ -718,9 +719,9 @@
 	  continue;
 	}
 
-	uint32_t src_px = reinterpret_cast<const uint32_t *> (data)[iy * width + ix];
+	uint32_t src_px = ((uint32_t) src_data[iy * width + ix]);
 	src_px = hb_raster_alpha_mul (src_px, clip_alpha);
-	row[px] = hb_raster_src_over (src_px, row[px]);
+	row[px] = hb_packed_t<uint32_t> (hb_raster_src_over (src_px, (uint32_t) row[px]));
 	gx += inv_xx;
 	gy += inv_yx;
       }
@@ -999,7 +1000,7 @@
     {
       for (unsigned py = clip.min_y; py < clip.max_y; py++)
       {
-	uint32_t *row = reinterpret_cast<uint32_t *> (surf->buffer.arrayZ + py * stride);
+	hb_packed_t<uint32_t> *row = (hb_packed_t<uint32_t> *) (surf->buffer.arrayZ + py * stride);
 	float gx = inv_xx * ((float) ((int) clip.min_x + ox) + 0.5f) + inv_xy * ((float) ((int) py + oy) + 0.5f) + inv_x0;
 	float gy = inv_yx * ((float) ((int) clip.min_x + ox) + 0.5f) + inv_yy * ((float) ((int) py + oy) + 0.5f) + inv_y0;
 	if (use_lut)
@@ -1008,7 +1009,7 @@
 	  {
 	    float proj_t = ((gx - gx0) * dx + (gy - gy0) * dy) * inv_denom;
 	    uint32_t src = lookup_gradient_lut (lut, proj_t, extend);
-	    row[px] = hb_raster_src_over (src, row[px]);
+	    row[px] = hb_packed_t<uint32_t> (hb_raster_src_over (src, (uint32_t) row[px]));
 	    gx += inv_xx;
 	    gy += inv_yx;
 	  }
@@ -1019,7 +1020,7 @@
 	  {
 	    float proj_t = ((gx - gx0) * dx + (gy - gy0) * dy) * inv_denom;
 	    uint32_t src = evaluate_color_line (stops, len, proj_t, extend);
-	    row[px] = hb_raster_src_over (src, row[px]);
+	    row[px] = hb_packed_t<uint32_t> (hb_raster_src_over (src, (uint32_t) row[px]));
 	    gx += inv_xx;
 	    gy += inv_yx;
 	  }
@@ -1030,7 +1031,7 @@
     {
       for (unsigned py = clip.min_y; py < clip.max_y; py++)
       {
-	uint32_t *row = reinterpret_cast<uint32_t *> (surf->buffer.arrayZ + py * stride);
+	hb_packed_t<uint32_t> *row = (hb_packed_t<uint32_t> *) (surf->buffer.arrayZ + py * stride);
 	const uint8_t *clip_row = clip.alpha.arrayZ + py * clip.stride;
 	float gx = inv_xx * ((float) ((int) clip.min_x + ox) + 0.5f) + inv_xy * ((float) ((int) py + oy) + 0.5f) + inv_x0;
 	float gy = inv_yx * ((float) ((int) clip.min_x + ox) + 0.5f) + inv_yy * ((float) ((int) py + oy) + 0.5f) + inv_y0;
@@ -1048,7 +1049,7 @@
 	    float proj_t = ((gx - gx0) * dx + (gy - gy0) * dy) * inv_denom;
 	    uint32_t src = lookup_gradient_lut (lut, proj_t, extend);
 	    src = hb_raster_alpha_mul (src, clip_alpha);
-	    row[px] = hb_raster_src_over (src, row[px]);
+	    row[px] = hb_packed_t<uint32_t> (hb_raster_src_over (src, (uint32_t) row[px]));
 	    gx += inv_xx;
 	    gy += inv_yx;
 	  }
@@ -1067,7 +1068,7 @@
 	    float proj_t = ((gx - gx0) * dx + (gy - gy0) * dy) * inv_denom;
 	    uint32_t src = evaluate_color_line (stops, len, proj_t, extend);
 	    src = hb_raster_alpha_mul (src, clip_alpha);
-	    row[px] = hb_raster_src_over (src, row[px]);
+	    row[px] = hb_packed_t<uint32_t> (hb_raster_src_over (src, (uint32_t) row[px]));
 	    gx += inv_xx;
 	    gy += inv_yx;
 	  }
@@ -1156,7 +1157,7 @@
     {
       for (unsigned py = clip.min_y; py < clip.max_y; py++)
       {
-	uint32_t *row = reinterpret_cast<uint32_t *> (surf->buffer.arrayZ + py * stride);
+	hb_packed_t<uint32_t> *row = (hb_packed_t<uint32_t> *) (surf->buffer.arrayZ + py * stride);
 	float gx = inv_xx * ((float) ((int) clip.min_x + ox) + 0.5f) + inv_xy * ((float) ((int) py + oy) + 0.5f) + inv_x0;
 	float gy = inv_yx * ((float) ((int) clip.min_x + ox) + 0.5f) + inv_yy * ((float) ((int) py + oy) + 0.5f) + inv_y0;
 	if (use_lut)
@@ -1200,7 +1201,7 @@
 	    }
 
 	    uint32_t src = lookup_gradient_lut (lut, grad_t, extend);
-	    row[px] = hb_raster_src_over (src, row[px]);
+	    row[px] = hb_packed_t<uint32_t> (hb_raster_src_over (src, (uint32_t) row[px]));
 	    gx += inv_xx;
 	    gy += inv_yx;
 	  }
@@ -1240,7 +1241,7 @@
 	    }
 
 	    uint32_t src = evaluate_color_line (stops, len, grad_t, extend);
-	    row[px] = hb_raster_src_over (src, row[px]);
+	    row[px] = hb_packed_t<uint32_t> (hb_raster_src_over (src, (uint32_t) row[px]));
 	    gx += inv_xx;
 	    gy += inv_yx;
 	  }
@@ -1251,7 +1252,7 @@
     {
       for (unsigned py = clip.min_y; py < clip.max_y; py++)
       {
-	uint32_t *row = reinterpret_cast<uint32_t *> (surf->buffer.arrayZ + py * stride);
+	hb_packed_t<uint32_t> *row = (hb_packed_t<uint32_t> *) (surf->buffer.arrayZ + py * stride);
 	const uint8_t *clip_row = clip.alpha.arrayZ + py * clip.stride;
 	float gx = inv_xx * ((float) ((int) clip.min_x + ox) + 0.5f) + inv_xy * ((float) ((int) py + oy) + 0.5f) + inv_x0;
 	float gy = inv_yx * ((float) ((int) clip.min_x + ox) + 0.5f) + inv_yy * ((float) ((int) py + oy) + 0.5f) + inv_y0;
@@ -1298,7 +1299,7 @@
 
 	    uint32_t src = lookup_gradient_lut (lut, grad_t, extend);
 	    src = hb_raster_alpha_mul (src, clip_alpha);
-	    row[px] = hb_raster_src_over (src, row[px]);
+	    row[px] = hb_packed_t<uint32_t> (hb_raster_src_over (src, (uint32_t) row[px]));
 	    gx += inv_xx;
 	    gy += inv_yx;
 	  }
@@ -1346,7 +1347,7 @@
 
 	    uint32_t src = evaluate_color_line (stops, len, grad_t, extend);
 	    src = hb_raster_alpha_mul (src, clip_alpha);
-	    row[px] = hb_raster_src_over (src, row[px]);
+	    row[px] = hb_packed_t<uint32_t> (hb_raster_src_over (src, (uint32_t) row[px]));
 	    gx += inv_xx;
 	    gy += inv_yx;
 	  }
@@ -1422,7 +1423,7 @@
     {
       for (unsigned py = clip.min_y; py < clip.max_y; py++)
       {
-	uint32_t *row = reinterpret_cast<uint32_t *> (surf->buffer.arrayZ + py * stride);
+	hb_packed_t<uint32_t> *row = (hb_packed_t<uint32_t> *) (surf->buffer.arrayZ + py * stride);
 	float gx = inv_xx * ((float) ((int) clip.min_x + ox) + 0.5f) + inv_xy * ((float) ((int) py + oy) + 0.5f) + inv_x0;
 	float gy = inv_yx * ((float) ((int) clip.min_x + ox) + 0.5f) + inv_yy * ((float) ((int) py + oy) + 0.5f) + inv_y0;
 	if (use_lut)
@@ -1433,7 +1434,7 @@
 	    if (angle < 0) angle += (float) HB_2_PI;
 	    float grad_t = (angle - a0) * inv_angle_range;
 	    uint32_t src = lookup_gradient_lut (lut, grad_t, extend);
-	    row[px] = hb_raster_src_over (src, row[px]);
+	    row[px] = hb_packed_t<uint32_t> (hb_raster_src_over (src, (uint32_t) row[px]));
 	    gx += inv_xx;
 	    gy += inv_yx;
 	  }
@@ -1446,7 +1447,7 @@
 	    if (angle < 0) angle += (float) HB_2_PI;
 	    float grad_t = (angle - a0) * inv_angle_range;
 	    uint32_t src = evaluate_color_line (stops, len, grad_t, extend);
-	    row[px] = hb_raster_src_over (src, row[px]);
+	    row[px] = hb_packed_t<uint32_t> (hb_raster_src_over (src, (uint32_t) row[px]));
 	    gx += inv_xx;
 	    gy += inv_yx;
 	  }
@@ -1457,7 +1458,7 @@
     {
       for (unsigned py = clip.min_y; py < clip.max_y; py++)
       {
-	uint32_t *row = reinterpret_cast<uint32_t *> (surf->buffer.arrayZ + py * stride);
+	hb_packed_t<uint32_t> *row = (hb_packed_t<uint32_t> *) (surf->buffer.arrayZ + py * stride);
 	const uint8_t *clip_row = clip.alpha.arrayZ + py * clip.stride;
 	float gx = inv_xx * ((float) ((int) clip.min_x + ox) + 0.5f) + inv_xy * ((float) ((int) py + oy) + 0.5f) + inv_x0;
 	float gy = inv_yx * ((float) ((int) clip.min_x + ox) + 0.5f) + inv_yy * ((float) ((int) py + oy) + 0.5f) + inv_y0;
@@ -1477,7 +1478,7 @@
 	    float grad_t = (angle - a0) * inv_angle_range;
 	    uint32_t src = lookup_gradient_lut (lut, grad_t, extend);
 	    src = hb_raster_alpha_mul (src, clip_alpha);
-	    row[px] = hb_raster_src_over (src, row[px]);
+	    row[px] = hb_packed_t<uint32_t> (hb_raster_src_over (src, (uint32_t) row[px]));
 	    gx += inv_xx;
 	    gy += inv_yx;
 	  }
@@ -1498,7 +1499,7 @@
 	    float grad_t = (angle - a0) * inv_angle_range;
 	    uint32_t src = evaluate_color_line (stops, len, grad_t, extend);
 	    src = hb_raster_alpha_mul (src, clip_alpha);
-	    row[px] = hb_raster_src_over (src, row[px]);
+	    row[px] = hb_packed_t<uint32_t> (hb_raster_src_over (src, (uint32_t) row[px]));
 	    gx += inv_xx;
 	    gy += inv_yx;
 	  }