+ // We can use memset.
+ memset(bitmapBuffer + xRangeMin, 0, (xRangeMax - xRangeMin) * sizeof(uint32_t));
+ bitmapBuffer += glyphData.width;
+ }
+ }
+ else
+ {
+ uint32_t packedStrikethroughColor = 0u;
+ uint8_t* packedStrikethroughColorBuffer = reinterpret_cast<uint8_t*>(&packedStrikethroughColor);
+
+ // Write the color to the pixel buffer
+ *(packedStrikethroughColorBuffer + 3u) = strikethroughColorAlpha;
+ *(packedStrikethroughColorBuffer + 2u) = static_cast<uint8_t>(strikethroughColor.b * strikethroughColorAlpha);
+ *(packedStrikethroughColorBuffer + 1u) = static_cast<uint8_t>(strikethroughColor.g * strikethroughColorAlpha);
+ *(packedStrikethroughColorBuffer) = static_cast<uint8_t>(strikethroughColor.r * strikethroughColorAlpha);
+
+ for(uint32_t y = yRangeMin; y < yRangeMax; y++)
+ {
+ for(uint32_t x = xRangeMin; x < xRangeMax; x++)
+ {
+ // Note : this is same logic as bitmap[y][x] = strikethroughColor;
+ *(bitmapBuffer + x) = packedStrikethroughColor;
+ }
+ bitmapBuffer += glyphData.width;
+ }
+ }
+}
+
+/**
+ * @brief Create an initialized image buffer filled with transparent color.
+ *
+ * Creates the pixel data used to generate the final image with the given size.
+ *
+ * @param[in] bufferWidth The width of the image buffer.
+ * @param[in] bufferHeight The height of the image buffer.
+ * @param[in] pixelFormat The format of the pixel in the image that the text is rendered as (i.e. either Pixel::BGRA8888 or Pixel::L8).
+ *
+ * @return An image buffer.
+ */
+inline Devel::PixelBuffer CreateTransparentImageBuffer(const uint32_t bufferWidth, const uint32_t bufferHeight, const Pixel::Format pixelFormat)
+{
+ Devel::PixelBuffer imageBuffer = Devel::PixelBuffer::New(bufferWidth, bufferHeight, pixelFormat);
+
+ if(Pixel::RGBA8888 == pixelFormat)
+ {
+ const uint32_t bufferSizeInt = bufferWidth * bufferHeight;
+ const size_t bufferSizeChar = sizeof(uint32_t) * static_cast<std::size_t>(bufferSizeInt);
+ memset(imageBuffer.GetBuffer(), 0, bufferSizeChar);
+ }
+ else
+ {
+ memset(imageBuffer.GetBuffer(), 0, static_cast<std::size_t>(bufferWidth * bufferHeight));
+ }
+
+ return imageBuffer;
+}
+
+/**
+ * @brief Combine the two RGBA image buffers together.
+ *
+ * The top layer buffer will blend over the bottom layer buffer:
+ * - If the pixel is not fully opaque from either buffer, it will be blended with
+ * the pixel from the other buffer and copied to the combined buffer.
+ * - If the pixels from both buffers are fully opaque, the pixels from the top layer
+ * buffer will be copied to the combined buffer.
+ *
+ * Due to the performance issue, We need to re-use input'ed pixelBuffer memory.
+ * We can determine which pixelBuffer's memory is destination
+ *
+ * @param[in, out] topPixelBuffer The top layer buffer.
+ * @param[in, out] bottomPixelBuffer The bottom layer buffer.
+ * @param[in] bufferWidth The width of the image buffer.
+ * @param[in] bufferHeight The height of the image buffer.
+ * @param[in] storeResultIntoTop True if we store the combined image buffer result into topPixelBuffer.
+ * False if we store the combined image buffer result into bottomPixelBuffer.
+ *
+ */
+void CombineImageBuffer(Devel::PixelBuffer& __restrict__ topPixelBuffer, Devel::PixelBuffer& __restrict__ bottomPixelBuffer, const uint32_t bufferWidth, const uint32_t bufferHeight, bool storeResultIntoTop)
+{
+ // Assume that we always combine two RGBA images
+ // Jump with 4bytes for optimize runtime.
+ uint32_t* topBuffer = reinterpret_cast<uint32_t*>(topPixelBuffer.GetBuffer());
+ uint32_t* bottomBuffer = reinterpret_cast<uint32_t*>(bottomPixelBuffer.GetBuffer());
+
+ if(topBuffer == NULL && bottomBuffer == NULL)
+ {
+ // Nothing to do if both buffers are empty.
+ return;
+ }
+
+ if(topBuffer == NULL)
+ {
+ // Nothing to do if topBuffer is empty.
+ // If we need to store the result into top, change topPixelBuffer as bottomPixelBuffer.
+ if(storeResultIntoTop)
+ {
+ topPixelBuffer = bottomPixelBuffer;
+ }
+ return;
+ }
+
+ if(bottomBuffer == NULL)
+ {
+ // Nothing to do if bottomBuffer is empty.
+ // If we need to store the result into bottom, change bottomPixelBuffer as topPixelBuffer.
+ if(!storeResultIntoTop)
+ {
+ bottomPixelBuffer = topPixelBuffer;