/// <inheritdoc/> public void Dispose() { this.lookahead?.Dispose(); this.valOffset?.Dispose(); this.maxcode?.Dispose(); this.huffval?.Dispose(); this.lookahead = null; this.valOffset = null; this.maxcode = null; this.huffval = null; }
/// <summary> /// Initializes a new instance of the <see cref="PdfJsHuffmanTable"/> struct. /// </summary> /// <param name="memoryManager">The <see cref="MemoryManager"/> to use for buffer allocations.</param> /// <param name="lengths">The code lengths</param> /// <param name="values">The huffman values</param> public PdfJsHuffmanTable(MemoryManager memoryManager, byte[] lengths, byte[] values) { // TODO: Replace FakeBuffer<T> usages with standard or array orfixed-sized arrays this.lookahead = memoryManager.AllocateFake <short>(256); this.valOffset = memoryManager.AllocateFake <short>(18); this.maxcode = memoryManager.AllocateFake <long>(18); using (IBuffer <short> huffsize = memoryManager.Allocate <short>(257)) using (IBuffer <short> huffcode = memoryManager.Allocate <short>(257)) { GenerateSizeTable(lengths, huffsize.Span); GenerateCodeTable(huffsize.Span, huffcode.Span); GenerateDecoderTables(lengths, huffcode.Span, this.valOffset.Span, this.maxcode.Span); GenerateLookaheadTables(lengths, values, this.lookahead.Span); } this.huffval = memoryManager.AllocateManagedByteBuffer(values.Length, true); Buffer.BlockCopy(values, 0, this.huffval.Array, 0, values.Length); this.MaxCode = this.maxcode.Array; this.ValOffset = this.valOffset.Array; this.HuffVal = this.huffval.Array; this.Lookahead = this.lookahead.Array; }
private void Return <T>(BasicArrayBuffer <T> buffer) where T : struct { this.returnLog.Add(new ReturnRequest(buffer.Array.GetHashCode())); }
/// <inheritdoc/> protected override void OnFrameApply(ImageFrame <TPixel> source, Rectangle sourceRectangle, Configuration configuration) { Region region = this.Region; Rectangle rect = region.Bounds; // Align start/end positions. int minX = Math.Max(0, rect.Left); int maxX = Math.Min(source.Width, rect.Right); int minY = Math.Max(0, rect.Top); int maxY = Math.Min(source.Height, rect.Bottom); if (minX >= maxX) { return; // no effect inside image; } if (minY >= maxY) { return; // no effect inside image; } int maxIntersections = region.MaxIntersections; float subpixelCount = 4; // we need to offset the pixel grid to account for when we outline a path. // basically if the line is [1,2] => [3,2] then when outlining at 1 we end up with a region of [0.5,1.5],[1.5, 1.5],[3.5,2.5],[2.5,2.5] // and this can cause missed fills when not using antialiasing.so we offset the pixel grid by 0.5 in the x & y direction thus causing the# // region to alline with the pixel grid. float offset = 0.5f; if (this.Options.Antialias) { offset = 0f; // we are antialising skip offsetting as real antalising should take care of offset. subpixelCount = this.Options.AntialiasSubpixelDepth; if (subpixelCount < 4) { subpixelCount = 4; } } using (BrushApplicator <TPixel> applicator = this.Brush.CreateApplicator(source, rect, this.Options)) { int scanlineWidth = maxX - minX; using (BasicArrayBuffer <float> buffer = source.MemoryManager.AllocateFake <float>(maxIntersections)) using (BasicArrayBuffer <float> scanline = source.MemoryManager.AllocateFake <float>(scanlineWidth)) { bool scanlineDirty = true; float subpixelFraction = 1f / subpixelCount; float subpixelFractionPoint = subpixelFraction / subpixelCount; for (int y = minY; y < maxY; y++) { if (scanlineDirty) { // clear the buffer for (int x = 0; x < scanlineWidth; x++) { scanline[x] = 0; } scanlineDirty = false; } float yPlusOne = y + 1; for (float subPixel = (float)y; subPixel < yPlusOne; subPixel += subpixelFraction) { int pointsFound = region.Scan(subPixel + offset, buffer.Array, 0); if (pointsFound == 0) { // nothing on this line skip continue; } QuickSort(new Span <float>(buffer.Array, 0, pointsFound)); for (int point = 0; point < pointsFound; point += 2) { // points will be paired up float scanStart = buffer[point] - minX; float scanEnd = buffer[point + 1] - minX; int startX = (int)MathF.Floor(scanStart + offset); int endX = (int)MathF.Floor(scanEnd + offset); if (startX >= 0 && startX < scanline.Length) { for (float x = scanStart; x < startX + 1; x += subpixelFraction) { scanline[startX] += subpixelFractionPoint; scanlineDirty = true; } } if (endX >= 0 && endX < scanline.Length) { for (float x = endX; x < scanEnd; x += subpixelFraction) { scanline[endX] += subpixelFractionPoint; scanlineDirty = true; } } int nextX = startX + 1; endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge nextX = Math.Max(nextX, 0); for (int x = nextX; x < endX; x++) { scanline[x] += subpixelFraction; scanlineDirty = true; } } } if (scanlineDirty) { if (!this.Options.Antialias) { for (int x = 0; x < scanlineWidth; x++) { if (scanline[x] >= 0.5) { scanline[x] = 1; } else { scanline[x] = 0; } } } applicator.Apply(scanline.Span, minX, y); } } } } }