public Image2Ascii() { activeChars = new string[] { " ·:+x#W@", " ░░▒▒▓▓█" }[0]; mCanvasSize = new Size(80, 25); mColorMode = ColorModes.GrayScale; mScanMode = ScanModes.Fast; mCharset = Charsets.Standard; mGrayScaleMode = GrayscaleModes.Average; mBackColor = Color.Black; mFont = new Font("Consolas", 12, GraphicsUnit.Pixel); SetCharSize(); }
private static void HandleCall(ref DependencyList list, NodeFactory factory, MethodIL methodIL, MethodDesc methodCalled, ref Tracker tracker, ScanModes modes) { bool scanningReflection = (modes & ScanModes.Reflection) != 0; bool scanningInterop = (modes & ScanModes.Interop) != 0; switch (methodCalled.Name) { // Enum.GetValues(Type) needs array of that type case "GetValues" when scanningReflection && methodCalled.OwningType == factory.TypeSystemContext.GetWellKnownType(WellKnownType.Enum): { TypeDesc type = tracker.GetLastType(); if (type != null && type.IsEnum && !type.IsGenericDefinition /* generic enums! */) { // Type could be something weird like MyEnum<object, __Canon> - normalize it type = type.NormalizeInstantiation(); list = list ?? new DependencyList(); list.Add(factory.ConstructedTypeSymbol(type.MakeArrayType()), "Enum.GetValues"); } } break; // Type.GetType(string...) needs the type with the given name case "GetType" when scanningReflection && methodCalled.OwningType.IsSystemType() && methodCalled.Signature.Length > 0: { string name = tracker.GetLastString(); if (name != null && methodIL.OwningMethod.OwningType is MetadataType mdType && ResolveType(name, mdType.Module, out TypeDesc type, out ModuleDesc referenceModule) && !factory.MetadataManager.IsReflectionBlocked(type)) { const string reason = "Type.GetType"; list = list ?? new DependencyList(); list.Add(factory.MaximallyConstructableType(type), reason); // Also add module metadata in case this reference was through a type forward if (factory.MetadataManager.CanGenerateMetadata(referenceModule.GetGlobalModuleType())) { list.Add(factory.ModuleMetadata(referenceModule), reason); } // Opportunistically remember the type so that it flows to Type.GetMethod if needed. tracker.TrackType(type); } } break; // Type.GetMethod(string...) case "GetMethod" when scanningReflection && methodCalled.OwningType.IsSystemType(): { string name = tracker.GetLastString(); TypeDesc type = tracker.GetLastType(); if (name != null && type != null) { HandleTypeGetMethod(ref list, factory, type, name, "Type.GetMethod"); } } break; // Type.GetProperty(string...) case "GetProperty" when scanningReflection && methodCalled.OwningType.IsSystemType(): { string name = tracker.GetLastString(); TypeDesc type = tracker.GetLastType(); if (name != null && type != null) { // Just do the easy thing and assume C# naming conventions HandleTypeGetMethod(ref list, factory, type, "get_" + name, "Type.GetProperty"); HandleTypeGetMethod(ref list, factory, type, "set_" + name, "Type.GetProperty"); } } break; case "SizeOf" when scanningInterop && IsMarshalSizeOf(methodCalled): { TypeDesc type = tracker.GetLastType(); if (IsTypeEligibleForMarshalSizeOfTracking(type)) { list = list ?? new DependencyList(); list.Add(factory.StructMarshallingData((DefType)type), "Marshal.SizeOf"); } } break; } }
public static void Scan(ref DependencyList list, NodeFactory factory, MethodIL methodIL, ScanModes modes) { ILReader reader = new ILReader(methodIL.GetILBytes()); Tracker tracker = new Tracker(methodIL); // The algorithm here is really primitive: we scan the IL forward in a single pass, remembering // the last type/string/token we saw. // // We then intrinsically recognize a couple methods that consume this information. // // This has obvious problems since we don't have exact knowledge of the parameters passed // (something being in front of a call doesn't mean it's a parameter to the call). But since // this is a heuristic, it's okay. We want this to be as fast as possible. // // The main purposes of this scanner is to make following patterns work: // // * Enum.GetValues(typeof(Foo)) - this is very common and we need to make sure Foo[] is compiled. // * Type.GetType("Foo, Bar").GetMethod("Blah") - framework uses this to work around layering problems. // * typeof(Foo<>).MakeGenericType(arg).GetMethod("Blah") - used in e.g. LINQ expressions implementation // * typeof(Foo<>).GetProperty("Blah") - used in e.g. LINQ expressions implementation // * Marshal.SizeOf(typeof(Foo)) - very common and we need to make sure interop data is generated while (reader.HasNext) { ILOpcode opcode = reader.ReadILOpcode(); switch (opcode) { case ILOpcode.ldstr: tracker.TrackStringToken(reader.ReadILToken()); break; case ILOpcode.ldtoken: int token = reader.ReadILToken(); if (IsTypeEqualityTest(methodIL, reader, out ILReader newReader)) { reader = newReader; } else { tracker.TrackLdTokenToken(token); TypeDesc type = methodIL.GetObject(token) as TypeDesc; if (type != null && !type.IsCanonicalSubtype(CanonicalFormKind.Any)) { list = list ?? new DependencyList(); list.Add(factory.MaximallyConstructableType(type), "Unknown LDTOKEN use"); } } break; case ILOpcode.call: case ILOpcode.callvirt: var method = methodIL.GetObject(reader.ReadILToken()) as MethodDesc; if (method != null) { HandleCall(ref list, factory, methodIL, method, ref tracker, modes); } break; default: reader.Skip(opcode); break; } } }
public void Scan(ScanModes.Scanmode __scmScanMode, double __dPixelTime, bool __bResend, bool master, double __dRotation, int delay, bool wobble, double wobbleAmplitude, bool flip) { int returnlength = 1000; if (__bResend | this.m_dScanCoordinates == null) { // We need to figure out the size of the full coordinate buffer. // This is the size of 1 period buffer * the number of lines/repeats of that buffer. int linesize = __scmScanMode.ScanCoordinates.GetLength(1); int numlines = __scmScanMode.RepeatNumber; int framesize = linesize * numlines; // The position offset between consecutive scanlines. double delta = this.NmToVoltage(__scmScanMode.ScanCoordinates[1, linesize - 1] - __scmScanMode.ScanCoordinates[1, 0]); // Allocate space for the full image double[,] coordinates = new double[3, framesize + returnlength]; // We compose line triggers for a single line and later copy it to the frame buffer. int[] levels = new int[linesize]; // The trigger buffer for the full frame. int[] longlevels = new int[framesize + returnlength]; foreach (Trigger t in __scmScanMode.Triggers) { if (t.Active) { // Set pixel trigger to ensure data acq on the actual scanline only (and not the ramping period) //for (int i = t.Start + delay; i < t.End + delay + 1; i++) for (int i = t.Start; i < t.End + 1; i++) { levels[i] = 1; } // Additionally set the line start and end triggers. //levels[t.Start + delay] = 3; //levels[t.End + delay] = 3; levels[t.Start] = 3; levels[t.End] = 3; } } // Final linebuffer double[,] linebuffer = new double[3, __scmScanMode.ScanCoordinates.Length / 2]; int szdouble = sizeof(double); int szint = sizeof(int); for (int i = 0; i < linesize; i++) { linebuffer[0, i] = this.NmToVoltage(__scmScanMode.ScanCoordinates[0, i]) + this.m_dCurrentVoltageX; linebuffer[1, i] = this.NmToVoltage(__scmScanMode.ScanCoordinates[1, i]) + this.m_dCurrentVoltageY; //linebuffer[2, i] = this.NmToVoltage(linebuffer[2, i]) + this.m_dCurrentVoltageZ; linebuffer[2, i] = this.m_dCurrentVoltageZ; } if (!wobble) { for (int i = 0; i < numlines; i++) { for (int j = 0; j < linesize; j++) { linebuffer[1, j] = linebuffer[1, j] + delta; } // Coordinates. System.Buffer.BlockCopy(linebuffer, 0 * szdouble, coordinates, (i * linesize) * szdouble, linesize * szdouble); System.Buffer.BlockCopy(linebuffer, linesize * szdouble, coordinates, ((i * linesize) + framesize + returnlength) * szdouble, linesize * szdouble); System.Buffer.BlockCopy(linebuffer, 2 * linesize * szdouble, coordinates, ((i * linesize) + 2 * (framesize + returnlength)) * szdouble, linesize * szdouble); // Triggers. //System.Buffer.BlockCopy(levels, 0 * szint, longlevels, i * linesize * szint, (linesize - 1) * szint); System.Buffer.BlockCopy(levels, 0 * szint, longlevels, (delay + (i * linesize)) * szint, (linesize - 1) * szint); //for (int j = 0; j < linesize; j++) //{ // coordinates[0, j + (i * linesize)] = this.m_dCurrentVoltageX + this.NmToVoltage(__scmScanMode.ScanCoordinates[0, j]); // coordinates[1, j + (i * linesize)] = this.m_dCurrentVoltageY + this.NmToVoltage(__scmScanMode.ScanCoordinates[1, j] + i * delta); // coordinates[2, j + (i * linesize)] = this.m_dCurrentVoltageZ + 0.0; // longlevels[j + (i * linesize)] = levels[j]; //} } } else { // Generate the wobble waveform double[] wobblewf = GenerateWobbleBuffer(this.NmToVoltage(wobbleAmplitude), framesize); for (int i = 0; i < framesize; i++) { wobblewf[i] = wobblewf[i] + this.m_dCurrentVoltageZ; } for (int i = 0; i < numlines; i++) { for (int j = 0; j < linesize; j++) { linebuffer[1, j] = linebuffer[1, j] + delta; } System.Buffer.BlockCopy(linebuffer, 0 * szdouble, coordinates, (i * linesize) * szdouble, linesize * szdouble); System.Buffer.BlockCopy(linebuffer, linesize * szdouble, coordinates, ((i * linesize) + framesize + returnlength) * szdouble, linesize * szdouble); System.Buffer.BlockCopy(linebuffer, 2 * linesize * szdouble, coordinates, ((i * linesize) + 2 * (framesize + returnlength)) * szdouble, linesize * szdouble); //System.Buffer.BlockCopy(levels, 0 * szint, longlevels, i * linesize * szint, (linesize - 1) * szint); System.Buffer.BlockCopy(levels, 0 * szint, longlevels, (delay + (i * linesize)) * szint, (linesize - 1) * szint); } System.Buffer.BlockCopy(wobblewf, 0 * szdouble, coordinates, 2 * (framesize + returnlength) * szdouble, framesize * szdouble); // We might need to flip channels. if (flip) { } //if (!wobble) //{ // for (int i = 0; i < __scmScanMode.RepeatNumber; i++) // { // for (int j = 0; j < linesize; j++) // { // coordinates[1, j + (i * linesize)] = this.m_dCurrentVoltageY + this.NmToVoltage(__scmScanMode.ScanCoordinates[0, j]); // coordinates[0, j + (i * linesize)] = this.m_dCurrentVoltageX + this.NmToVoltage(__scmScanMode.ScanCoordinates[1, j] + i * delta); // coordinates[2, j + (i * linesize)] = this.m_dCurrentVoltageZ + 0.0; // longlevels[j + (i * linesize)] = levels[j]; // } // } //} //else //{ // double[] sine = GenerateWobbleBuffer(this.NmToVoltage(wobbleAmplitude), linesize * __scmScanMode.RepeatNumber); // for (int i = 0; i < __scmScanMode.RepeatNumber; i++) // { // for (int j = 0; j < linesize; j++) // { // coordinates[1, j + (i * linesize)] = this.m_dCurrentVoltageY + this.NmToVoltage(__scmScanMode.ScanCoordinates[0, j]); // coordinates[0, j + (i * linesize)] = this.m_dCurrentVoltageX + this.NmToVoltage(__scmScanMode.ScanCoordinates[1, j] + i * delta); // coordinates[2, j + (i * linesize)] = this.m_dCurrentVoltageZ + sine[j + (i * linesize)]; // longlevels[j + (i * linesize)] = levels[j]; // } // } //} } // TODO: Evaluate if rotation is still a desirable function to have. //double _dMidX = this.NmToVoltage(__scmScanMode.XScanSizeNm) / 2 + this.m_dCurrentVoltageX; //double _dMidY = this.m_dCurrentVoltageY; //for (int i = 0; i < coordinates.GetLength(1); i++) //{ // double xt = _dMidX + Math.Cos(__dRotation) * (coordinates[0, i] - _dMidX) - Math.Sin(__dRotation) * (coordinates[1, i] - _dMidY); // double yt = _dMidY + Math.Sin(__dRotation) * (coordinates[0, i] - _dMidX) + Math.Cos(__dRotation) * (coordinates[1, i] - _dMidY); // coordinates[0, i] = xt; // coordinates[1, i] = yt; //} // Calculate a smooth return upon frame end. This is FlipXY independent. double[,] returnpath = this.CalculateMove( coordinates[0, (linesize * __scmScanMode.RepeatNumber) - 1], coordinates[1, (linesize * __scmScanMode.RepeatNumber) - 1], coordinates[2, (linesize * __scmScanMode.RepeatNumber) - 1], coordinates[0, 0], coordinates[1, 0], coordinates[2, 0], returnlength); //for (int i = 0; i < returnlength; i++) //{ // coordinates[0, linesize * __scmScanMode.RepeatNumber + i] = returnpath[0, i]; // coordinates[1, linesize * __scmScanMode.RepeatNumber + i] = returnpath[1, i]; // coordinates[2, linesize * __scmScanMode.RepeatNumber + i] = returnpath[2, i]; //} System.Buffer.BlockCopy(returnpath, 0 * szdouble, coordinates, framesize * szdouble, returnlength * szdouble); System.Buffer.BlockCopy(returnpath, returnlength * szdouble, coordinates, (2 * framesize + returnlength) * szdouble, returnlength * szdouble); System.Buffer.BlockCopy(returnpath, 2 * returnlength * szdouble, coordinates, (2 * (framesize + returnlength) + framesize) * szdouble, returnlength * szdouble); // Set the levels to achieve start of frame and end of frame trigger. longlevels[0 + delay] = 4; longlevels[longlevels.GetLength(0) + delay - returnlength] = 4; // Persist. this.m_iLongLevels = longlevels; this.m_dScanCoordinates = coordinates; } // Persist. this.m_dMoveGeneratorCoordinates = this.m_dScanCoordinates; this.m_startX = this.m_dScanCoordinates[0, 0]; this.m_startY = this.m_dScanCoordinates[1, 0]; this.m_startZ = this.m_dScanCoordinates[2, 0]; // Perform the actual scan as a timed move. //this.TimedMove(__dPixelTime, this.m_dScanCoordinates, this.m_iLongLevels, false); this.TimedMove(__dPixelTime, this.m_dScanCoordinates, this.m_iLongLevels, master, true); }
private static void HandleCall(ref DependencyList list, NodeFactory factory, MethodIL methodIL, MethodDesc methodCalled, ref Tracker tracker, ScanModes modes) { bool scanningReflection = (modes & ScanModes.Reflection) != 0; bool scanningInterop = (modes & ScanModes.Interop) != 0; switch (methodCalled.Name) { // Enum.GetValues(Type) needs array of that type case "GetValues" when scanningReflection && methodCalled.OwningType == factory.TypeSystemContext.GetWellKnownType(WellKnownType.Enum): { TypeDesc type = tracker.GetLastType(); if (type != null && type.IsEnum && !type.IsGenericDefinition /* generic enums! */) { // Type could be something weird like MyEnum<object, __Canon> - normalize it type = type.NormalizeInstantiation(); list = list ?? new DependencyList(); list.Add(factory.ConstructedTypeSymbol(type.MakeArrayType()), "Enum.GetValues"); } } break; // Type.GetType(string...) needs the type with the given name case "GetType" when scanningReflection && methodCalled.OwningType.IsSystemType() && methodCalled.Signature.Length > 0: { string name = tracker.GetLastString(); if (name != null && methodIL.OwningMethod.OwningType is MetadataType mdType && ResolveType(name, mdType.Module, out TypeDesc type, out ModuleDesc referenceModule) && !factory.MetadataManager.IsReflectionBlocked(type)) { const string reason = "Type.GetType"; list = list ?? new DependencyList(); list.Add(factory.MaximallyConstructableType(type), reason); // Also add module metadata in case this reference was through a type forward if (factory.MetadataManager.CanGenerateMetadata(referenceModule.GetGlobalModuleType())) { list.Add(factory.ModuleMetadata(referenceModule), reason); } // Opportunistically remember the type so that it flows to Type.GetMethod if needed. tracker.TrackType(type); } } break; // Type.GetMethod(string...) case "GetMethod" when scanningReflection && methodCalled.OwningType.IsSystemType(): { string name = tracker.GetLastString(); TypeDesc type = tracker.GetLastType(); if (name != null && type != null && !factory.MetadataManager.IsReflectionBlocked(type)) { if (type.IsGenericDefinition) { Instantiation inst = TypeExtensions.GetInstantiationThatMeetsConstraints(type.Instantiation, allowCanon: false); if (inst.IsNull) { break; } type = ((MetadataType)type).MakeInstantiatedType(inst); list = list ?? new DependencyList(); list.Add(factory.MaximallyConstructableType(type), "Type.GetMethod"); } else { // Type could be something weird like SomeType<object, __Canon> - normalize it type = type.NormalizeInstantiation(); } MethodDesc reflectedMethod = type.GetMethod(name, null); if (reflectedMethod != null && !factory.MetadataManager.IsReflectionBlocked(reflectedMethod)) { if (reflectedMethod.HasInstantiation) { // Don't want to accidentally get Foo<__Canon>.Bar<object>() if (reflectedMethod.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any)) { break; } Instantiation inst = TypeExtensions.GetInstantiationThatMeetsConstraints(reflectedMethod.Instantiation, allowCanon: false); if (inst.IsNull) { break; } reflectedMethod = reflectedMethod.MakeInstantiatedMethod(inst); } const string reason = "Type.GetMethod"; list = list ?? new DependencyList(); if (reflectedMethod.IsVirtual) { RootVirtualMethodForReflection(ref list, factory, reflectedMethod, reason); } if (!reflectedMethod.IsAbstract) { list.Add(factory.CanonicalEntrypoint(reflectedMethod), reason); if (reflectedMethod.HasInstantiation && reflectedMethod != reflectedMethod.GetCanonMethodTarget(CanonicalFormKind.Specific)) { list.Add(factory.MethodGenericDictionary(reflectedMethod), reason); } } } } } break; case "SizeOf" when scanningInterop && IsMarshalSizeOf(methodCalled): { TypeDesc type = tracker.GetLastType(); if (IsTypeEligibleForMarshalSizeOfTracking(type)) { list = list ?? new DependencyList(); list.Add(factory.StructMarshallingData((DefType)type), "Marshal.SizeOf"); } } break; } }