public void Multiply(TransformationMatrix m) { //performance optimalization: try to avoid multiple calculations. if (1 == m.a && 0 == m.b && 0 == m.c && 1 == m.d ) { //offset only. //this.Translate(m.OffsetX, m.OffsetY); } else { //complex matrix TransformationMatrix n = this.Clone(); a = m.a * n.a + m.b * n.c; b = m.a * n.b + m.b * n.d; c = m.c * n.a + m.d * n.c; d = m.c * n.b + m.d * n.d; e = m.e * n.a + m.f * n.c + n.e; f = m.e * n.b + m.f * n.d + n.f; } }
private static int GetTransformationIndex(TransformationMatrix transformationMatrix, BoundsInches imageBounds) { int[] vector = new int[4]; vector[0] = GetSignOrZero(transformationMatrix.a); vector[1] = GetSignOrZero(transformationMatrix.b); vector[2] = GetSignOrZero(transformationMatrix.c); vector[3] = GetSignOrZero(transformationMatrix.d); int result = 0; // Default is to use the original picture for(int i = 0; i < 8; i++) { bool match = true; for(int j = 0; j < 4; j++) { if(fTransformationArray[i, j] != vector[j]) { match = false; } } if(match) { result = i; } } // TODO: Calculate imageBounds imageBounds = null; return result; }
private static TransformationMatrix GetTransformationMatrix(BoundsInches imageBounds, int transformationIndex) { TransformationMatrix result = new TransformationMatrix(); result.a = fTransformationArray[transformationIndex, 0]; result.b = fTransformationArray[transformationIndex, 1]; result.c = fTransformationArray[transformationIndex, 2]; result.d = fTransformationArray[transformationIndex, 3]; result.e = fTransformationArray[transformationIndex, 4]; result.f = fTransformationArray[transformationIndex, 5]; result.a *= imageBounds.Width; result.b *= imageBounds.Height; result.c *= imageBounds.Width; result.d *= imageBounds.Height; result.e *= imageBounds.Width; result.e += imageBounds.X; result.f *= imageBounds.Height; result.f += imageBounds.Y; result.a *= 72; result.b *= 72; result.c *= 72; result.d *= 72; result.e *= 72; result.f *= 72; return result; }
public TransformationMatrix Transpose() { TransformationMatrix result = new TransformationMatrix(); result.cell[0,0] = this.cell[0,0]; result.cell[0,1] = this.cell[1,0]; result.cell[0,2] = this.cell[2,0]; result.cell[0,3] = this.cell[3,0]; result.cell[1,0] = this.cell[0,1]; result.cell[1,1] = this.cell[1,1]; result.cell[1,2] = this.cell[2,1]; result.cell[1,3] = this.cell[3,1]; result.cell[2,0] = this.cell[0,2]; result.cell[2,1] = this.cell[1,2]; result.cell[2,2] = this.cell[2,2]; result.cell[2,3] = this.cell[3,2]; result.cell[3,0] = this.cell[0,3]; result.cell[3,1] = this.cell[1,3]; result.cell[3,2] = this.cell[2,3]; result.cell[3,3] = this.cell[3,3]; return result; }
static double RowDotCol(int iRow, TransformationMatrix left, double[] right) { return left.cell[iRow,0]*right[0] + left.cell[iRow,1]*right[1] + left.cell[iRow,2]*right[2] + left.cell[iRow,3]*right[3]; }
static double RowDotCol(int iRow, int iCol, TransformationMatrix left, TransformationMatrix right) { return left.cell[iRow,0]*right.cell[0,iCol] + left.cell[iRow,1]*right.cell[1,iCol] + left.cell[iRow,2]*right.cell[2,iCol] + left.cell[iRow,3]*right.cell[3,iCol]; }
public static TransformationMatrix operator*(TransformationMatrix me, TransformationMatrix him) { TransformationMatrix result = new TransformationMatrix(); result.cell[0,0] = RowDotCol(0,0,me, him); result.cell[0,1] = RowDotCol(0,1,me, him); result.cell[0,2] = RowDotCol(0,2,me, him); result.cell[0,3] = RowDotCol(0,3,me, him); result.cell[1,0] = RowDotCol(1,0,me, him); result.cell[1,1] = RowDotCol(1,1,me, him); result.cell[1,2] = RowDotCol(1,2,me, him); result.cell[1,3] = RowDotCol(1,3,me, him); result.cell[2,0] = RowDotCol(2,0,me, him); result.cell[2,1] = RowDotCol(2,1,me, him); result.cell[2,2] = RowDotCol(2,2,me, him); result.cell[2,3] = RowDotCol(2,3,me, him); result.cell[3,0] = RowDotCol(3,0,me, him); result.cell[3,1] = RowDotCol(3,1,me, him); result.cell[3,2] = RowDotCol(3,2,me, him); result.cell[3,3] = RowDotCol(3,3,me, him); return result; }
public TransformationMatrix Inverse() // Return the inverse matrix. Code here generated automatically from Mathematica. { TransformationMatrix result = new TransformationMatrix(); double denom = ((((cell[0, 2] * (cell[1, 0] * (cell[2, 3] * cell[3, 1] - cell[2, 1] * cell[3, 3]) + cell[1, 1] * (cell[2, 0] * cell[3, 3] - cell[2, 3] * cell[3, 0]) + cell[1, 3] * (cell[2, 1] * cell[3, 0] - cell[2, 0] * cell[3, 1])) + cell[0, 3] * (cell[1, 0] * (cell[2, 1] * cell[3, 2] - cell[2, 2] * cell[3, 1]) + cell[1, 1] * (cell[2, 2] * cell[3, 0] - cell[2, 0] * cell[3, 2]) + cell[1, 2] * (cell[2, 0] * cell[3, 1] - cell[2, 1] * cell[3, 0])) + cell[3, 3] * (cell[0, 0] * (cell[1, 2] * cell[2, 1] - cell[1, 1] * cell[2, 2]) + cell[0, 1] * (cell[1, 0] * cell[2, 2] - cell[1, 2] * cell[2, 0])) + cell[0, 0] * cell[1, 1] * cell[2, 3] * cell[3, 2] + cell[0, 0] * cell[1, 3] * cell[2, 2] * cell[3, 1] + cell[0, 1] * cell[1, 2] * cell[2, 3] * cell[3, 0] + cell[0, 1] * cell[1, 3] * cell[2, 0] * cell[3, 2]) - cell[0, 1] * cell[1, 0] * cell[2, 3] * cell[3, 2]) - cell[0, 0] * cell[1, 3] * cell[2, 1] * cell[3, 2]) - cell[0, 0] * cell[1, 2] * cell[2, 3] * cell[3, 1]) - cell[0, 1] * cell[1, 3] * cell[2, 2] * cell[3, 0]; result.cell[0,0] = (cell[1,1] * (cell[2,3] * cell[3,2] - cell[2,2] * cell[3,3]) + cell[1,2] * (cell[2,1] * cell[3,3] - cell[2,3] * cell[3,1]) + cell[1,3] * (cell[2,2] * cell[3,1] - cell[2,1] * cell[3,2]) ) / denom; result.cell[0,1] = (cell[0,1] * (cell[2,2] * cell[3,3] - cell[2,3] * cell[3,2]) + cell[0,2] * (cell[2,3] * cell[3,1] - cell[2,1] * cell[3,3]) + cell[0,3] * (cell[2,1] * cell[3,2] - cell[2,2] * cell[3,1]) ) / denom; result.cell[0,2] = (cell[0,1] * (cell[1,3] * cell[3,2] - cell[1,2] * cell[3,3]) + cell[0,2] * (cell[1,1] * cell[3,3] - cell[1,3] * cell[3,1]) + cell[0,3] * (cell[1,2] * cell[3,1] - cell[1,1] * cell[3,2]) ) / denom; result.cell[0,3] = (cell[0,1] * (cell[1,2] * cell[2,3] - cell[1,3] * cell[2,2]) + cell[0,2] * (cell[1,3] * cell[2,1] - cell[1,1] * cell[2,3]) + cell[0,3] * (cell[1,1] * cell[2,2] - cell[1,2] * cell[2,1]) ) / denom; result.cell[1,0] = (cell[1,0] * (cell[2,2] * cell[3,3] - cell[2,3] * cell[3,2]) + cell[1,2] * (cell[2,3] * cell[3,0] - cell[2,0] * cell[3,3]) + cell[1,3] * (cell[2,0] * cell[3,2] - cell[2,2] * cell[3,0]) ) / denom; result.cell[1,1] = (cell[0,0] * (cell[2,3] * cell[3,2] - cell[2,2] * cell[3,3]) + cell[0,2] * (cell[2,0] * cell[3,3] - cell[2,3] * cell[3,0]) + cell[0,3] * (cell[2,2] * cell[3,0] - cell[2,0] * cell[3,2]) ) / denom; result.cell[1,2] = (cell[0,0] * (cell[1,2] * cell[3,3] - cell[1,3] * cell[3,2]) + cell[0,2] * (cell[1,3] * cell[3,0] - cell[1,0] * cell[3,3]) + cell[0,3] * (cell[1,0] * cell[3,2] - cell[1,2] * cell[3,0]) ) / denom; result.cell[1,3] = (cell[0,0] * (cell[1,3] * cell[2,2] - cell[1,2] * cell[2,3]) + cell[0,2] * (cell[1,0] * cell[2,3] - cell[1,3] * cell[2,0]) + cell[0,3] * (cell[1,2] * cell[2,0] - cell[1,0] * cell[2,2]) ) / denom; result.cell[2,0] = (cell[1,0] * (cell[2,3] * cell[3,1] - cell[2,1] * cell[3,3]) + cell[1,1] * (cell[2,0] * cell[3,3] - cell[2,3] * cell[3,0]) + cell[1,3] * (cell[2,1] * cell[3,0] - cell[2,0] * cell[3,1]) ) / denom; result.cell[2,1] = (cell[0,0] * (cell[2,1] * cell[3,3] - cell[2,3] * cell[3,1]) + cell[0,1] * (cell[2,3] * cell[3,0] - cell[2,0] * cell[3,3]) + cell[0,3] * (cell[2,0] * cell[3,1] - cell[2,1] * cell[3,0]) ) / denom; result.cell[2,2] = (cell[0,0] * (cell[1,3] * cell[3,1] - cell[1,1] * cell[3,3]) + cell[0,1] * (cell[1,0] * cell[3,3] - cell[1,3] * cell[3,0]) + cell[0,3] * (cell[1,1] * cell[3,0] - cell[1,0] * cell[3,1]) ) / denom; result.cell[2,3] = (cell[0,0] * (cell[1,1] * cell[2,3] - cell[1,3] * cell[2,1]) + cell[0,1] * (cell[1,3] * cell[2,0] - cell[1,0] * cell[2,3]) + cell[0,3] * (cell[1,0] * cell[2,1] - cell[1,1] * cell[2,0]) ) / denom; result.cell[3,0] = (cell[1,0] * (cell[2,1] * cell[3,2] - cell[2,2] * cell[3,1]) + cell[1,1] * (cell[2,2] * cell[3,0] - cell[2,0] * cell[3,2]) + cell[1,2] * (cell[2,0] * cell[3,1] - cell[2,1] * cell[3,0]) ) / denom; result.cell[3,1] = (cell[0,0] * (cell[2,2] * cell[3,1] - cell[2,1] * cell[3,2]) + cell[0,1] * (cell[2,0] * cell[3,2] - cell[2,2] * cell[3,0]) + cell[0,2] * (cell[2,1] * cell[3,0] - cell[2,0] * cell[3,1]) ) / denom; result.cell[3,2] = (cell[0,0] * (cell[1,1] * cell[3,2] - cell[1,2] * cell[3,1]) + cell[0,1] * (cell[1,2] * cell[3,0] - cell[1,0] * cell[3,2]) + cell[0,2] * (cell[1,0] * cell[3,1] - cell[1,1] * cell[3,0]) ) / denom; result.cell[3,3] = (cell[0,0] * (cell[1,2] * cell[2,1] - cell[1,1] * cell[2,2]) + cell[0,1] * (cell[1,0] * cell[2,2] - cell[1,2] * cell[2,0]) + cell[0,2] * (cell[1,1] * cell[2,0] - cell[1,0] * cell[2,1]) ) / denom; return result; }
public void test2() { var matrix = new TransformationMatrix(1, 0, 0, 1, 0, 0); matrix.Multiply(new TransformationMatrix(1, 0, 0, 1, 0, 0)); AssertEquals(1.0, matrix.A); }
internal void UpdateLocation(TransformationMatrix transform) { foreach (HalfEdge3Vertex v in m_Mesh.Vertices) { double x = transform[0, 0] * v.X + transform[0, 1] * v.Y + transform[0, 2] * v.Z + transform[0, 3]; double y = transform[1, 0] * v.X + transform[1, 1] * v.Y + transform[1, 2] * v.Z + transform[1, 3]; double z = transform[2, 0] * v.X + transform[2, 1] * v.Y + transform[2, 2] * v.Z + transform[2, 3]; v.X = x; v.Y = y; v.Z = z; } m_transformationMatrix = transform * m_transformationMatrix; }
internal virtual void Rotate(double angle, Vector3D direction) { Vector3D d = direction.Unit(); double x = d.X; double y = d.Y; double z = d.Z; TransformationMatrix m = new TransformationMatrix(); double c = Math.Cos(angle); double s = Math.Sin(angle); m[0,0] = (x*x) * (1-c)+c; m[1,0] = x*y * (1-c)-z*s; m[2,0] = x*z * (1-c)+y*s; m[0,1] = y*x * (1-c)+z*s; m[1,1] = (y*y) * (1-c)+c; m[2,1] = y*z * (1-c)-x*s; m[0,2] = x*z * (1-c)-y*s; m[1,2] = y*z * (1-c)+x*s; m[2,2] = (z*z) * (1-c)+c; UpdateLocation(m); m = m.Invert().Transpose(); foreach (Vector3D v in m_Mesh.Normals) { double x0 = m[0, 0] * v.X + m[0, 1] * v.Y + m[0, 2] * v.Z + m[0, 3]; double y0 = m[1, 0] * v.X + m[1, 1] * v.Y + m[1, 2] * v.Z + m[1, 3]; double z0 = m[2, 0] * v.X + m[2, 1] * v.Y + m[2, 2] * v.Z + m[2, 3]; v.X = x0; v.Y = y0; v.Z = z0; } }
public void ModifyCurrentTransformationMatrix(double[] value) { var ctm = GetCurrentState().CurrentTransformationMatrix; GetCurrentState().CurrentTransformationMatrix = TransformationMatrix.FromArray(value).Multiply(ctm); }
private void AdjustTextMatrix(double tx, double ty) { var matrix = TransformationMatrix.GetTranslationMatrix(tx, ty); TextMatrices.TextMatrix = matrix.Multiply(TextMatrices.TextMatrix); }
public void ShowText(IInputBytes bytes) { var currentState = GetCurrentState(); var font = currentState.FontState.FromExtendedGraphicsState ? activeExtendedGraphicsStateFont : resourceStore.GetFont(currentState.FontState.FontName); if (font == null) { throw new InvalidOperationException($"Could not find the font with name {currentState.FontState.FontName} in the resource store. It has not been loaded yet."); } var fontSize = currentState.FontState.FontSize; var horizontalScaling = currentState.FontState.HorizontalScaling / 100.0; var characterSpacing = currentState.FontState.CharacterSpacing; var rise = currentState.FontState.Rise; var transformationMatrix = currentState.CurrentTransformationMatrix; var renderingMatrix = TransformationMatrix.FromValues(fontSize * horizontalScaling, 0, 0, fontSize, 0, rise); var pointSize = Math.Round(transformationMatrix.Multiply(TextMatrices.TextMatrix).Transform(new PdfRectangle(0, 0, 1, fontSize)).Height, 2); while (bytes.MoveNext()) { var code = font.ReadCharacterCode(bytes, out int codeLength); var foundUnicode = font.TryGetUnicode(code, out var unicode); if (!foundUnicode || unicode == null) { log.Warn($"We could not find the corresponding character with code {code} in font {font.Name}."); // Try casting directly to string as in PDFBox 1.8. unicode = new string((char)code, 1); } var wordSpacing = 0.0; if (code == ' ' && codeLength == 1) { wordSpacing += GetCurrentState().FontState.WordSpacing; } var textMatrix = TextMatrices.TextMatrix; if (font.IsVertical) { if (!(font is IVerticalWritingSupported verticalFont)) { throw new InvalidOperationException($"Font {font.Name} was in vertical writing mode but did not implement {nameof(IVerticalWritingSupported)}."); } var positionVector = verticalFont.GetPositionVector(code); textMatrix = textMatrix.Translate(positionVector.X, positionVector.Y); } var boundingBox = font.GetBoundingBox(code); var transformedGlyphBounds = PerformantRectangleTransformer .Transform(renderingMatrix, textMatrix, transformationMatrix, boundingBox.GlyphBounds); var transformedPdfBounds = PerformantRectangleTransformer .Transform(renderingMatrix, textMatrix, transformationMatrix, new PdfRectangle(0, 0, boundingBox.Width, 0)); // If the text rendering mode calls for filling, the current nonstroking color in the graphics state is used; // if it calls for stroking, the current stroking color is used. // In modes that perform both filling and stroking, the effect is as if each glyph outline were filled and then stroked in separate operations. // TODO: expose color as something more advanced var color = currentState.FontState.TextRenderingMode != TextRenderingMode.Stroke ? currentState.CurrentNonStrokingColor : currentState.CurrentStrokingColor; Letter letter = null; if (Diacritics.IsInCombiningDiacriticRange(unicode) && bytes.CurrentOffset > 0 && letters.Count > 0) { var attachTo = letters[letters.Count - 1]; if (attachTo.TextSequence == textSequence && Diacritics.TryCombineDiacriticWithPreviousLetter(unicode, attachTo.Value, out var newLetter)) { // TODO: union of bounding boxes. letters.Remove(attachTo); letter = new Letter( newLetter, attachTo.GlyphRectangle, attachTo.StartBaseLine, attachTo.EndBaseLine, attachTo.Width, attachTo.FontSize, attachTo.Font, attachTo.Color, attachTo.PointSize, attachTo.TextSequence); } else { letter = new Letter( unicode, transformedGlyphBounds, transformedPdfBounds.BottomLeft, transformedPdfBounds.BottomRight, transformedPdfBounds.Width, fontSize, font.Details, color, pointSize, textSequence); } } else { letter = new Letter( unicode, transformedGlyphBounds, transformedPdfBounds.BottomLeft, transformedPdfBounds.BottomRight, transformedPdfBounds.Width, fontSize, font.Details, color, pointSize, textSequence); } letters.Add(letter); markedContentStack.AddLetter(letter); double tx, ty; if (font.IsVertical) { var verticalFont = (IVerticalWritingSupported)font; var displacement = verticalFont.GetDisplacementVector(code); tx = 0; ty = (displacement.Y * fontSize) + characterSpacing + wordSpacing; } else { tx = (boundingBox.Width * fontSize + characterSpacing + wordSpacing) * horizontalScaling; ty = 0; } TextMatrices.TextMatrix = TextMatrices.TextMatrix.Translate(tx, ty); } }