コード例 #1
0
    protected void Interpret(Graphics g)
    {
      this._isMeasureInSync = false; // if structure is changed, the measure is out of sync

      char[] searchchars = new Char[] { '\\', '\r', '\n', ')' };

      // Modification of StringFormat is necessary to avoid 
      // too big spaces between successive words
      StringFormat strfmt = (StringFormat)StringFormat.GenericTypographic.Clone();
      strfmt.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;

      strfmt.LineAlignment = StringAlignment.Far;
      strfmt.Alignment = StringAlignment.Near;

      // next statement is necessary to have a consistent string length both
      // on 0 degree rotated text and rotated text
      // without this statement, the text is fitted to the pixel grid, which
      // leads to "steps" during scaling
      g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

      MeasureFont(g, _font, out _cyBaseLineSpace, out _cyBaseAscent, out _cyBaseDescent);

      System.Collections.Stack itemstack = new System.Collections.Stack();

      Font currFont = (Font)_font.Clone();


      if(null!=_cachedTextLines)
        _cachedTextLines.Clear(); // delete old contents 
      else
        _cachedTextLines = new TextLine.TextLineCollection();


      TextLine currTextLine = new TextLine();
        
      // create a new text line first
      _cachedTextLines.Add(currTextLine);
      int currTxtIdx = 0;

      TextItem currTextItem = new TextItem(currFont);
      //      TextItem firstItem = currTextItem; // preserve the first item
      


      currTextLine.Add(currTextItem);


      while(currTxtIdx<_text.Length)
      {

        // search for the first occurence of a backslash
        int bi = _text.IndexOfAny(searchchars,currTxtIdx);

        if(bi<0) // nothing was found
        {
          // move the rest of the text to the current item
          currTextItem.Text += _text.Substring(currTxtIdx,_text.Length-currTxtIdx);
          currTxtIdx = _text.Length;
        }
        else // something was found
        {
          // first finish the current item by moving the text from
          // currTxtIdx to (bi-1) to the current text item
          currTextItem.Text += _text.Substring(currTxtIdx,bi-currTxtIdx);
          
          if('\r'==_text[bi]) // carriage return character : simply ignore it
          {
            // simply ignore this character, since we search for \n
            currTxtIdx=bi+1;
          }
          else if('\n'==_text[bi]) // newline character : create a new line
          {
            currTxtIdx = bi+1;
            // create a new line
            currTextLine = new TextLine();
            _cachedTextLines.Add(currTextLine);
            // create also a new text item
            currTextItem = new TextItem(currTextItem,null);
            currTextLine.Add(currTextItem);
          }
          else if('\\'==_text[bi]) // backslash : look what comes after
          {
            if(bi+1<_text.Length && (')'==_text[bi+1] || '\\'==_text[bi+1])) // if a closing brace or a backslash, take these as chars
            {
              currTextItem.Text += _text[bi+1];
              currTxtIdx = bi+2;
            }
              // if the backslash not followed by a symbol and than a (, 
            else if(bi+3<_text.Length && !char.IsSeparator(_text,bi+1) && '('==_text[bi+2])
            {
              switch(_text[bi+1])
              {
                case 'b':
                case 'B':
                {
                  itemstack.Push(currTextItem);
                  currTextItem = new TextItem(currTextItem, new Font(currTextItem.Font.FontFamily,currTextItem.Font.Size,currTextItem.Font.Style | FontStyle.Bold, GraphicsUnit.World));
                  currTextLine.Add(currTextItem);
                  currTxtIdx = bi+3;
                }
                  break; // bold
                case 'i':
                case 'I':
                {
                  itemstack.Push(currTextItem);
                  currTextItem = new TextItem(currTextItem, new Font(currTextItem.Font.FontFamily,currTextItem.Font.Size,currTextItem.Font.Style | FontStyle.Italic, GraphicsUnit.World));
                  currTextLine.Add(currTextItem);
                  currTxtIdx = bi+3;
                }
                  break; // italic
                case 'u':
                case 'U':
                {
                  itemstack.Push(currTextItem);
                  currTextItem = new TextItem(currTextItem, new Font(currTextItem.Font.FontFamily,currTextItem.Font.Size,currTextItem.Font.Style | FontStyle.Underline, GraphicsUnit.World));
                  currTextLine.Add(currTextItem);
                  currTxtIdx = bi+3;
                }
                  break; // underlined
                case 's':
                case 'S': // strikeout
                {
                  itemstack.Push(currTextItem);
                  currTextItem = new TextItem(currTextItem, new Font(currTextItem.Font.FontFamily,currTextItem.Font.Size,currTextItem.Font.Style | FontStyle.Strikeout, GraphicsUnit.World));
                  currTextLine.Add(currTextItem);
                  currTxtIdx = bi+3;
                }
                  break; // end strikeout
                case 'g':
                case 'G':
                {
                  itemstack.Push(currTextItem);
                  currTextItem = new TextItem(currTextItem, new Font("Symbol",currTextItem.Font.Size,currTextItem.Font.Style, GraphicsUnit.World));
                  currTextLine.Add(currTextItem);
                  currTxtIdx = bi+3;
                }
                  break; // underlined
                case '+':
                case '-':
                {
                  itemstack.Push(currTextItem);
                  // measure the current font size
                  float cyLineSpace,cyAscent,cyDescent;
                  MeasureFont(g,currTextItem.Font,out cyLineSpace, out cyAscent, out cyDescent);
                  
                  currTextItem = new TextItem(currTextItem, new Font(currTextItem.Font.FontFamily,0.65f*currTextItem.Font.Size,currTextItem.Font.Style, GraphicsUnit.World));
                  currTextLine.Add(currTextItem);
                  currTextItem.m_SubIndex += ('+'==_text[bi+1] ? 1 : -1);


                  if('-'==_text[bi+1]) 
                    currTextItem.m_yShift += 0.15f*cyAscent; // Carefull: plus (+) means shift down
                  else
                    currTextItem.m_yShift -= 0.35f*cyAscent; // be carefull: minus (-) means shift up
                  
                  currTxtIdx = bi+3;
                }
                  break; // underlined
                case 'l': // Plot Curve Symbol
                case 'L':
                {
                  // parse the arguments
                  // either in the Form 
                  // \L(PlotCurveNumber) or
                  // \L(LayerNumber, PlotCurveNumber) or
                  // \L(LayerNumber, PlotCurveNumber, DataPointNumber)


                  // find the corresponding closing brace
                  int closingbracepos = _text.IndexOf(")",bi+1);
                  if(closingbracepos<0) // no brace found, so threat this as normal text
                  {
                    currTextItem.Text += _text.Substring(bi,3);
                    currTxtIdx += 3;
                    continue;
                  }
                  // count the commas between here and the closing brace to get
                  // the number of arguments
                  int parsepos=bi+3;
                  int[] arg = new int[3];
                  int args;
                  for(args=0;args<3 && parsepos<closingbracepos;args++)
                  {
                    int commapos = _text.IndexOf(",",parsepos,closingbracepos-parsepos);
                    int endpos = commapos>0 ? commapos : closingbracepos; // the end of this argument
                    try { arg[args]=System.Convert.ToInt32(_text.Substring(parsepos,endpos-parsepos)); }
                    catch(Exception) { break; }
                    parsepos = endpos+1;
                  }
                  if(args==0) // if not successfully parsed at least one number
                  {
                    currTextItem.Text += _text.Substring(bi,3);
                    currTxtIdx += 3;
                    continue;   // handle it as if it where normal text
                  }

                  // itemstack.Push(currTextItem); // here we don't need to put the item on the stack, since we pared until the closing brace
                  currTextItem = new TextItem(currTextItem,null);
                  currTextLine.Add(currTextItem);
                  currTextItem.SetAsSymbol(args,arg);

                  currTextItem = new TextItem(currTextItem,null); // create a normal text item behind the symbol item
                  currTextLine.Add(currTextItem); // to have room for the following text
                  currTxtIdx = closingbracepos+1;
                }
                  break; // curve symbol
                case '%': // Plot Curve Name
                {
                  // parse the arguments
                  // either in the Form 
                  // \%(PlotCurveNumber) or
                  // \%(LayerNumber, PlotCurveNumber) or
                  Match match;
                  int layerNumber=-1;
                  int plotNumber=-1;
                  string plotLabelStyle=null;
                  bool   plotLabelStyleIsPropColName=false;
                  if((match = _regexIntArgument.Match(_text,bi+2)).Success)
                  {
                    plotNumber = int.Parse(match.Result("${argone}"));
                  }
                  else if((match = _regexIntIntArgument.Match(_text,bi+2)).Success)
                  {
                    layerNumber = int.Parse(match.Result("${argone}"));
                    plotNumber =  int.Parse(match.Result("${argtwo}"));
                  }
                  else if((match = _regexIntQstrgArgument.Match(_text,bi+2)).Success)
                  {
                    plotNumber     = int.Parse(match.Result("${argone}"));
                    plotLabelStyle =  match.Result("${argtwo}");
                    plotLabelStyleIsPropColName=true;
                  }
                  else if((match = _regexIntStrgArgument.Match(_text,bi+2)).Success)
                  {
                    plotNumber     = int.Parse(match.Result("${argone}"));
                    plotLabelStyle =  match.Result("${argtwo}");
                  }
                  else if((match = _regexIntIntStrgArgument.Match(_text,bi+2)).Success)
                  {
                    layerNumber = int.Parse(match.Result("${argone}"));
                    plotNumber =  int.Parse(match.Result("${argtwo}"));
                    plotLabelStyle = match.Result("${argthree}");
                  }
                  else if((match = _regexIntIntQstrgArgument.Match(_text,bi+2)).Success)
                  {
                    layerNumber = int.Parse(match.Result("${argone}"));
                    plotNumber =  int.Parse(match.Result("${argtwo}"));
                    plotLabelStyle = match.Result("${argthree}");
                    plotLabelStyleIsPropColName=true;
                  }
      
                  if(match.Success)
                  {
                    itemstack.Push(currTextItem);
                    currTextItem = new TextItem(currTextItem,null);
                    currTextLine.Add(currTextItem);
                    currTextItem.SetAsPlotCurveName(layerNumber,plotNumber,plotLabelStyle,plotLabelStyleIsPropColName);

                    currTextItem = new TextItem(currTextItem,null); // create a normal text item behind the symbol item
                    currTextLine.Add(currTextItem); // to have room for the following text
                    currTxtIdx = bi+2+match.Length;
                  }
                  else
                  {
                    currTextItem.Text += _text.Substring(bi,2);
                    currTxtIdx += 3;
                    continue;   // handle it as if it where normal text
                  }
                }
                  break; // percent symbol
                default:
                  // take the sequence as it is
                  currTextItem.Text += _text.Substring(bi,3);
                  currTxtIdx = bi+3;
                  break;
              } // end of switch
            }
            else // if no formatting and also no closing brace or backslash, take it as it is
            {
              currTextItem.Text += _text[bi];
              currTxtIdx = bi+1;
            }
          } // end if it was a backslash
          else if(')'==_text[bi]) // closing brace
          {
            // the formating is finished, we can return to the formating of the previous section
            if(itemstack.Count>0)
            {
              TextItem preservedprevious = (TextItem)itemstack.Pop();
              currTextItem = new TextItem(preservedprevious,null);
              currTextLine.Add(currTextItem);
              currTxtIdx = bi+1;
            }
            else // if the stack is empty, take the brace as it is, and use the default style
            {
              currTextItem.Text += _text[bi];
              currTxtIdx = bi+1;
            }

          }
        }

      } // end of while loop

      this._isStructureInSync=true; // now the text was interpreted
    }