forked from mirrors/gecko-dev
		
	This patch was automatically generated using the following script:
function convert() {
echo "Converting $1 to $2..."
find . \
       ! -wholename "*/.git*" \
       ! -wholename "obj-ff-dbg*" \
         -type f \
      \( -iname "*.cpp" \
         -o -iname "*.h" \
         -o -iname "*.c" \
         -o -iname "*.cc" \
         -o -iname "*.idl" \
         -o -iname "*.ipdl" \
         -o -iname "*.ipdlh" \
         -o -iname "*.mm" \) | \
    xargs -n 1 sed -i -e "s/\b$1\b/$2/g"
}
convert MOZ_OVERRIDE override
convert MOZ_FINAL final
		
	
			
		
			
				
	
	
		
			670 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			670 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
						|
/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
/* utilities for regression tests based on frame tree comparison */
 | 
						|
 
 | 
						|
#include "nsIFrameUtil.h"
 | 
						|
#include "nsFrame.h"
 | 
						|
#include "nsString.h"
 | 
						|
#include "nsRect.h"
 | 
						|
#include <stdlib.h>
 | 
						|
#include "plstr.h"
 | 
						|
 | 
						|
 | 
						|
#ifdef DEBUG
 | 
						|
class nsFrameUtil : public nsIFrameUtil {
 | 
						|
protected:
 | 
						|
  virtual ~nsFrameUtil();
 | 
						|
 | 
						|
public:
 | 
						|
  nsFrameUtil();
 | 
						|
 | 
						|
  NS_DECL_ISUPPORTS
 | 
						|
 | 
						|
  NS_IMETHOD CompareRegressionData(FILE* aFile1, FILE* aFile2,int32_t aRegressionOutput=0) override;
 | 
						|
  NS_IMETHOD DumpRegressionData(FILE* aInputFile, FILE* aOutputFile) override;
 | 
						|
 | 
						|
  struct Node;
 | 
						|
  struct Tag;
 | 
						|
 | 
						|
  struct NodeList {
 | 
						|
    NodeList();
 | 
						|
    ~NodeList();
 | 
						|
 | 
						|
    static void Destroy(NodeList* aLists);
 | 
						|
 | 
						|
    NodeList* next;            // for lists of lists
 | 
						|
    Node* node;
 | 
						|
    char* name;
 | 
						|
  };
 | 
						|
 | 
						|
  struct Node {
 | 
						|
    Node();
 | 
						|
    ~Node();
 | 
						|
 | 
						|
    static void Destroy(Node* aNode);
 | 
						|
 | 
						|
    static Node* Read(FILE* aFile, Tag* aTag);
 | 
						|
 | 
						|
    static Node* ReadTree(FILE* aFile);
 | 
						|
 | 
						|
    Node* next;
 | 
						|
    char* type;
 | 
						|
    uint32_t state;
 | 
						|
    nsRect bbox;
 | 
						|
    nsCString styleData;
 | 
						|
    NodeList* lists;
 | 
						|
  };
 | 
						|
 | 
						|
  struct Tag {
 | 
						|
    Tag();
 | 
						|
    ~Tag();
 | 
						|
 | 
						|
    static Tag* Parse(FILE* aFile);
 | 
						|
 | 
						|
    void AddAttr(char* aAttr, char* aValue);
 | 
						|
 | 
						|
    const char* GetAttr(const char* aAttr);
 | 
						|
 | 
						|
    void ReadAttrs(FILE* aFile);
 | 
						|
 | 
						|
    void ToString(nsString& aResult);
 | 
						|
 | 
						|
    enum Type {
 | 
						|
      open,
 | 
						|
      close,
 | 
						|
      openClose
 | 
						|
    };
 | 
						|
 | 
						|
    char* name;
 | 
						|
    Type type;
 | 
						|
    char** attributes;
 | 
						|
    int32_t num;
 | 
						|
    int32_t size;
 | 
						|
    char** values;
 | 
						|
  };
 | 
						|
 | 
						|
  static char* Copy(const char* aString);
 | 
						|
 | 
						|
  static void DumpNode(Node* aNode, FILE* aOutputFile, int32_t aIndent);
 | 
						|
  static void DumpTree(Node* aNode, FILE* aOutputFile, int32_t aIndent);
 | 
						|
  static bool CompareTrees(Node* aNode1, Node* aNode2);
 | 
						|
};
 | 
						|
 | 
						|
char*
 | 
						|
nsFrameUtil::Copy(const char* aString)
 | 
						|
{
 | 
						|
  if (aString) {
 | 
						|
    int l = ::strlen(aString);
 | 
						|
    char* c = new char[l+1];
 | 
						|
    if (!c)
 | 
						|
      return nullptr;
 | 
						|
    memcpy(c, aString, l+1);
 | 
						|
    return c;
 | 
						|
  }
 | 
						|
  return nullptr;
 | 
						|
}
 | 
						|
 | 
						|
//----------------------------------------------------------------------
 | 
						|
 | 
						|
nsFrameUtil::NodeList::NodeList()
 | 
						|
  : next(nullptr), node(nullptr), name(nullptr)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
nsFrameUtil::NodeList::~NodeList()
 | 
						|
{
 | 
						|
  if (nullptr != name) {
 | 
						|
    delete name;
 | 
						|
  }
 | 
						|
  if (nullptr != node) {
 | 
						|
    Node::Destroy(node);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
nsFrameUtil::NodeList::Destroy(NodeList* aLists)
 | 
						|
{
 | 
						|
  while (nullptr != aLists) {
 | 
						|
    NodeList* next = aLists->next;
 | 
						|
    delete aLists;
 | 
						|
    aLists = next;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
//----------------------------------------------------------------------
 | 
						|
 | 
						|
nsFrameUtil::Node::Node()
 | 
						|
  : next(nullptr), type(nullptr), state(0), lists(nullptr)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
nsFrameUtil::Node::~Node()
 | 
						|
{
 | 
						|
  if (nullptr != type) {
 | 
						|
    delete type;
 | 
						|
  }
 | 
						|
  if (nullptr != lists) {
 | 
						|
    NodeList::Destroy(lists);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
nsFrameUtil::Node::Destroy(Node* aList)
 | 
						|
{
 | 
						|
  while (nullptr != aList) {
 | 
						|
    Node* next = aList->next;
 | 
						|
    delete aList;
 | 
						|
    aList = next;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
static int32_t GetInt(nsFrameUtil::Tag* aTag, const char* aAttr)
 | 
						|
{
 | 
						|
  const char* value = aTag->GetAttr(aAttr);
 | 
						|
  if (nullptr != value) {
 | 
						|
    return int32_t( atoi(value) );
 | 
						|
  }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
nsFrameUtil::Node*
 | 
						|
nsFrameUtil::Node::ReadTree(FILE* aFile)
 | 
						|
{
 | 
						|
  Tag* tag = Tag::Parse(aFile);
 | 
						|
  if (nullptr == tag) {
 | 
						|
    return nullptr;
 | 
						|
  }
 | 
						|
  if (PL_strcmp(tag->name, "frame") != 0) {
 | 
						|
    delete tag;
 | 
						|
    return nullptr;
 | 
						|
  }
 | 
						|
  Node* result = Read(aFile, tag);
 | 
						|
  fclose(aFile);
 | 
						|
  return result;
 | 
						|
}
 | 
						|
 | 
						|
nsFrameUtil::Node*
 | 
						|
nsFrameUtil::Node::Read(FILE* aFile, Tag* tag)
 | 
						|
{
 | 
						|
  Node* node = new Node;
 | 
						|
  node->type = Copy(tag->GetAttr("type"));
 | 
						|
  if (!node->type) {
 | 
						|
    /* crash() */
 | 
						|
  }
 | 
						|
  node->state = GetInt(tag, "state");
 | 
						|
  delete tag;
 | 
						|
 | 
						|
  for (;;) {
 | 
						|
    tag = Tag::Parse(aFile);
 | 
						|
    if (nullptr == tag) break;
 | 
						|
    if (PL_strcmp(tag->name, "frame") == 0) {
 | 
						|
      delete tag;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    if (PL_strcmp(tag->name, "bbox") == 0) {
 | 
						|
      nscoord x = nscoord( GetInt(tag, "x") );
 | 
						|
      nscoord y = nscoord( GetInt(tag, "y") );
 | 
						|
      nscoord w = nscoord( GetInt(tag, "w") );
 | 
						|
      nscoord h = nscoord( GetInt(tag, "h") );
 | 
						|
      node->bbox.SetRect(x, y, w, h);
 | 
						|
    }
 | 
						|
    else if (PL_strcmp(tag->name, "child-list") == 0) {
 | 
						|
      NodeList* list = new NodeList();
 | 
						|
      list->name = Copy(tag->GetAttr("name"));
 | 
						|
      if (!list->name) {
 | 
						|
        /* crash() */
 | 
						|
      }
 | 
						|
      list->next = node->lists;
 | 
						|
      node->lists = list;
 | 
						|
      delete tag;
 | 
						|
 | 
						|
      Node** tailp = &list->node;
 | 
						|
      for (;;) {
 | 
						|
        tag = Tag::Parse(aFile);
 | 
						|
        if (nullptr == tag) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        if (PL_strcmp(tag->name, "child-list") == 0) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        if (PL_strcmp(tag->name, "frame") != 0) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        Node* child = Node::Read(aFile, tag);
 | 
						|
        if (nullptr == child) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        *tailp = child;
 | 
						|
        tailp = &child->next;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else if((PL_strcmp(tag->name, "font") == 0) ||
 | 
						|
            (PL_strcmp(tag->name, "color") == 0) ||
 | 
						|
            (PL_strcmp(tag->name, "spacing") == 0) ||
 | 
						|
            (PL_strcmp(tag->name, "list") == 0) ||
 | 
						|
            (PL_strcmp(tag->name, "position") == 0) ||
 | 
						|
            (PL_strcmp(tag->name, "text") == 0) ||
 | 
						|
            (PL_strcmp(tag->name, "display") == 0) ||
 | 
						|
            (PL_strcmp(tag->name, "table") == 0) ||
 | 
						|
            (PL_strcmp(tag->name, "content") == 0) ||
 | 
						|
            (PL_strcmp(tag->name, "UI") == 0) ||
 | 
						|
            (PL_strcmp(tag->name, "print") == 0)) {
 | 
						|
      const char* attr = tag->GetAttr("data");
 | 
						|
      node->styleData.Append('|');
 | 
						|
      node->styleData.Append(attr ? attr : "null attr");
 | 
						|
    }
 | 
						|
 | 
						|
    delete tag;
 | 
						|
  }
 | 
						|
  return node;
 | 
						|
}
 | 
						|
 | 
						|
//----------------------------------------------------------------------
 | 
						|
 | 
						|
nsFrameUtil::Tag::Tag()
 | 
						|
  : name(nullptr), type(open), attributes(nullptr), num(0), size(0),
 | 
						|
    values(nullptr)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
nsFrameUtil::Tag::~Tag()
 | 
						|
{
 | 
						|
  int32_t i, n = num;
 | 
						|
  if (0 != n) {
 | 
						|
    for (i = 0; i < n; i++) {
 | 
						|
      delete attributes[i];
 | 
						|
      delete values[i];
 | 
						|
    }
 | 
						|
    delete attributes;
 | 
						|
    delete values;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
nsFrameUtil::Tag::AddAttr(char* aAttr, char* aValue)
 | 
						|
{
 | 
						|
  if (num == size) {
 | 
						|
    int32_t newSize = size * 2 + 4;
 | 
						|
    char** a = new char*[newSize];
 | 
						|
    char** v = new char*[newSize];
 | 
						|
    if (0 != num) {
 | 
						|
      memcpy(a, attributes, num * sizeof(char*));
 | 
						|
      memcpy(v, values, num * sizeof(char*));
 | 
						|
      delete attributes;
 | 
						|
      delete values;
 | 
						|
    }
 | 
						|
    attributes = a;
 | 
						|
    values = v;
 | 
						|
    size = newSize;
 | 
						|
  }
 | 
						|
  attributes[num] = aAttr;
 | 
						|
  values[num] = aValue;
 | 
						|
  num = num + 1;
 | 
						|
}
 | 
						|
 | 
						|
const char*
 | 
						|
nsFrameUtil::Tag::GetAttr(const char* aAttr)
 | 
						|
{
 | 
						|
  int32_t i, n = num;
 | 
						|
  for (i = 0; i < n; i++) {
 | 
						|
    if (PL_strcmp(attributes[i], aAttr) == 0) {
 | 
						|
      return values[i];
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return nullptr;
 | 
						|
}
 | 
						|
 | 
						|
static inline int IsWhiteSpace(int c) {
 | 
						|
  return (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r');
 | 
						|
}
 | 
						|
 | 
						|
static bool EatWS(FILE* aFile)
 | 
						|
{
 | 
						|
  for (;;) {
 | 
						|
    int c = getc(aFile);
 | 
						|
    if (c < 0) {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    if (!IsWhiteSpace(c)) {
 | 
						|
      ungetc(c, aFile);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
static bool Expect(FILE* aFile, char aChar)
 | 
						|
{
 | 
						|
  int c = getc(aFile);
 | 
						|
  if (c < 0) return false;
 | 
						|
  if (c != aChar) {
 | 
						|
    ungetc(c, aFile);
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
static char* ReadIdent(FILE* aFile)
 | 
						|
{
 | 
						|
  char id[1000];
 | 
						|
  char* ip = id;
 | 
						|
  char* end = ip + sizeof(id) - 1;
 | 
						|
  while (ip < end) {
 | 
						|
    int c = fgetc(aFile);
 | 
						|
    if (c < 0) return nullptr;
 | 
						|
    if ((c == '=') || (c == '>') || (c == '/') || IsWhiteSpace(c)) {
 | 
						|
      ungetc(c, aFile);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    *ip++ = char(c);
 | 
						|
  }
 | 
						|
  *ip = '\0';
 | 
						|
  return nsFrameUtil::Copy(id);
 | 
						|
  /* may return a null pointer */
 | 
						|
}
 | 
						|
 | 
						|
static char* ReadString(FILE* aFile)
 | 
						|
{
 | 
						|
  if (!Expect(aFile, '\"')) {
 | 
						|
    return nullptr;
 | 
						|
  }
 | 
						|
  char id[1000];
 | 
						|
  char* ip = id;
 | 
						|
  char* end = ip + sizeof(id) - 1;
 | 
						|
  while (ip < end) {
 | 
						|
    int c = fgetc(aFile);
 | 
						|
    if (c < 0) return nullptr;
 | 
						|
    if (c == '\"') {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    *ip++ = char(c);
 | 
						|
  }
 | 
						|
  *ip = '\0';
 | 
						|
  return nsFrameUtil::Copy(id);
 | 
						|
  /* may return a null pointer */
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
nsFrameUtil::Tag::ReadAttrs(FILE* aFile)
 | 
						|
{
 | 
						|
  for (;;) {
 | 
						|
    if (!EatWS(aFile)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    int c = getc(aFile);
 | 
						|
    if (c < 0) break;
 | 
						|
    if (c == '/') {
 | 
						|
      if (!EatWS(aFile)) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      if (Expect(aFile, '>')) {
 | 
						|
        type = openClose;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else if (c == '>') {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    ungetc(c, aFile);
 | 
						|
    char* attr = ReadIdent(aFile);
 | 
						|
    if ((nullptr == attr) || !EatWS(aFile)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    char* value = nullptr;
 | 
						|
    if (Expect(aFile, '=')) {
 | 
						|
      value = ReadString(aFile);
 | 
						|
      if (nullptr == value) {
 | 
						|
        delete [] attr;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    AddAttr(attr, value);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
nsFrameUtil::Tag*
 | 
						|
nsFrameUtil::Tag::Parse(FILE* aFile)
 | 
						|
{
 | 
						|
  if (!EatWS(aFile)) {
 | 
						|
    return nullptr;
 | 
						|
  }
 | 
						|
  if (Expect(aFile, '<')) {
 | 
						|
    Tag* tag = new Tag;
 | 
						|
    if (Expect(aFile, '/')) {
 | 
						|
      tag->type = close;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      tag->type = open;
 | 
						|
    }
 | 
						|
    tag->name = ReadIdent(aFile);
 | 
						|
    tag->ReadAttrs(aFile);
 | 
						|
    return tag;
 | 
						|
  }
 | 
						|
  return nullptr;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
nsFrameUtil::Tag::ToString(nsString& aResult)
 | 
						|
{
 | 
						|
  aResult.Truncate();
 | 
						|
  aResult.Append(char16_t('<'));
 | 
						|
  if (type == close) {
 | 
						|
    aResult.Append(char16_t('/'));
 | 
						|
  }
 | 
						|
  aResult.AppendASCII(name);
 | 
						|
  if (0 != num) {
 | 
						|
    int32_t i, n = num;
 | 
						|
    for (i = 0; i < n; i++) {
 | 
						|
      aResult.Append(char16_t(' '));
 | 
						|
      aResult.AppendASCII(attributes[i]);
 | 
						|
      if (values[i]) {
 | 
						|
        aResult.AppendLiteral("=\"");
 | 
						|
        aResult.AppendASCII(values[i]);
 | 
						|
        aResult.Append(char16_t('\"'));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (type == openClose) {
 | 
						|
    aResult.Append(char16_t('/'));
 | 
						|
  }
 | 
						|
  aResult.Append(char16_t('>'));
 | 
						|
}
 | 
						|
 | 
						|
//----------------------------------------------------------------------
 | 
						|
 | 
						|
nsresult
 | 
						|
NS_NewFrameUtil(nsIFrameUtil** aResult)
 | 
						|
{
 | 
						|
  NS_PRECONDITION(nullptr != aResult, "null pointer");
 | 
						|
  if (nullptr == aResult) {
 | 
						|
    return NS_ERROR_NULL_POINTER;
 | 
						|
  }
 | 
						|
 | 
						|
  nsFrameUtil* it = new nsFrameUtil();
 | 
						|
 | 
						|
  NS_ADDREF(*aResult = it);
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsFrameUtil::nsFrameUtil()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
nsFrameUtil::~nsFrameUtil()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
NS_IMPL_ISUPPORTS(nsFrameUtil, nsIFrameUtil)
 | 
						|
 | 
						|
void
 | 
						|
nsFrameUtil::DumpNode(Node* aNode, FILE* aOutputFile, int32_t aIndent)
 | 
						|
{
 | 
						|
  nsFrame::IndentBy(aOutputFile, aIndent);
 | 
						|
  fprintf(aOutputFile, "%s 0x%x %d,%d,%d,%d, %s\n", aNode->type, aNode->state,
 | 
						|
          aNode->bbox.x, aNode->bbox.y,
 | 
						|
          aNode->bbox.width, aNode->bbox.height,
 | 
						|
          aNode->styleData.get());
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
nsFrameUtil::DumpTree(Node* aNode, FILE* aOutputFile, int32_t aIndent)
 | 
						|
{
 | 
						|
  while (nullptr != aNode) {
 | 
						|
    DumpNode(aNode, aOutputFile, aIndent);
 | 
						|
    nsFrameUtil::NodeList* lists = aNode->lists;
 | 
						|
    if (nullptr != lists) {
 | 
						|
      while (nullptr != lists) {
 | 
						|
        nsFrame::IndentBy(aOutputFile, aIndent);
 | 
						|
        fprintf(aOutputFile, " list: %s\n",
 | 
						|
                lists->name ? lists->name : "primary");
 | 
						|
        DumpTree(lists->node, aOutputFile, aIndent + 1);
 | 
						|
        lists = lists->next;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    aNode = aNode->next;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
nsFrameUtil::CompareTrees(Node* tree1, Node* tree2)
 | 
						|
{
 | 
						|
  bool result = true;
 | 
						|
  for (;; tree1 = tree1->next, tree2 = tree2->next) {
 | 
						|
    // Make sure both nodes are non-null, or at least agree with each other
 | 
						|
    if (nullptr == tree1) {
 | 
						|
      if (nullptr == tree2) {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      printf("first tree prematurely ends\n");
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    else if (nullptr == tree2) {
 | 
						|
      printf("second tree prematurely ends\n");
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
    // Check the attributes that we care about
 | 
						|
    if (0 != PL_strcmp(tree1->type, tree2->type)) {
 | 
						|
      printf("frame type mismatch: %s vs. %s\n", tree1->type, tree2->type);
 | 
						|
      printf("Node 1:\n");
 | 
						|
      DumpNode(tree1, stdout, 1);
 | 
						|
      printf("Node 2:\n");
 | 
						|
      DumpNode(tree2, stdout, 1);
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
    // Ignore the XUL scrollbar frames
 | 
						|
    static const char kScrollbarFrame[] = "ScrollbarFrame";
 | 
						|
    if (0 == PL_strncmp(tree1->type, kScrollbarFrame, sizeof(kScrollbarFrame) - 1))
 | 
						|
      continue;
 | 
						|
 | 
						|
    if (tree1->state != tree2->state) {
 | 
						|
      printf("frame state mismatch: 0x%x vs. 0x%x\n",
 | 
						|
             tree1->state, tree2->state);
 | 
						|
      printf("Node 1:\n");
 | 
						|
      DumpNode(tree1, stdout, 1);
 | 
						|
      printf("Node 2:\n");
 | 
						|
      DumpNode(tree2, stdout, 1);
 | 
						|
      result = false; // we have a non-critical failure, so remember that but continue
 | 
						|
    }
 | 
						|
    if (tree1->bbox.IsEqualInterior(tree2->bbox)) {
 | 
						|
      printf("frame bbox mismatch: %d,%d,%d,%d vs. %d,%d,%d,%d\n",
 | 
						|
             tree1->bbox.x, tree1->bbox.y,
 | 
						|
             tree1->bbox.width, tree1->bbox.height,
 | 
						|
             tree2->bbox.x, tree2->bbox.y,
 | 
						|
             tree2->bbox.width, tree2->bbox.height);
 | 
						|
      printf("Node 1:\n");
 | 
						|
      DumpNode(tree1, stdout, 1);
 | 
						|
      printf("Node 2:\n");
 | 
						|
      DumpNode(tree2, stdout, 1);
 | 
						|
      result = false; // we have a non-critical failure, so remember that but continue
 | 
						|
    }
 | 
						|
    if (tree1->styleData != tree2->styleData) {
 | 
						|
      printf("frame style data mismatch: %s vs. %s\n",
 | 
						|
        tree1->styleData.get(),
 | 
						|
        tree2->styleData.get());
 | 
						|
    }
 | 
						|
 | 
						|
    // Check child lists too
 | 
						|
    NodeList* list1 = tree1->lists;
 | 
						|
    NodeList* list2 = tree2->lists;
 | 
						|
    for (;;) {
 | 
						|
      if (nullptr == list1) {
 | 
						|
        if (nullptr != list2) {
 | 
						|
          printf("first tree prematurely ends (no child lists)\n");
 | 
						|
          printf("Node 1:\n");
 | 
						|
          DumpNode(tree1, stdout, 1);
 | 
						|
          printf("Node 2:\n");
 | 
						|
          DumpNode(tree2, stdout, 1);
 | 
						|
          return false;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (nullptr == list2) {
 | 
						|
        printf("second tree prematurely ends (no child lists)\n");
 | 
						|
        printf("Node 1:\n");
 | 
						|
        DumpNode(tree1, stdout, 1);
 | 
						|
        printf("Node 2:\n");
 | 
						|
        DumpNode(tree2, stdout, 1);
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
      if (0 != PL_strcmp(list1->name, list2->name)) {
 | 
						|
        printf("child-list name mismatch: %s vs. %s\n",
 | 
						|
               list1->name ? list1->name : "(null)",
 | 
						|
               list2->name ? list2->name : "(null)");
 | 
						|
        result = false; // we have a non-critical failure, so remember that but continue
 | 
						|
      }
 | 
						|
      else {
 | 
						|
        bool equiv = CompareTrees(list1->node, list2->node);
 | 
						|
        if (!equiv) {
 | 
						|
          return equiv;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      list1 = list1->next;
 | 
						|
      list2 = list2->next;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return result;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
nsFrameUtil::CompareRegressionData(FILE* aFile1, FILE* aFile2,int32_t aRegressionOutput)
 | 
						|
{
 | 
						|
  Node* tree1 = Node::ReadTree(aFile1);
 | 
						|
  Node* tree2 = Node::ReadTree(aFile2);
 | 
						|
 | 
						|
  nsresult rv = NS_OK;
 | 
						|
  if (!CompareTrees(tree1, tree2)) {
 | 
						|
    // only output this if aRegressionOutput is 0
 | 
						|
    if( 0 == aRegressionOutput ){
 | 
						|
      printf("Regression data 1:\n");
 | 
						|
      DumpTree(tree1, stdout, 0);
 | 
						|
      printf("Regression data 2:\n");
 | 
						|
      DumpTree(tree2, stdout, 0);
 | 
						|
    }
 | 
						|
    rv = NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  Node::Destroy(tree1);
 | 
						|
  Node::Destroy(tree2);
 | 
						|
 | 
						|
  return rv;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
nsFrameUtil::DumpRegressionData(FILE* aInputFile, FILE* aOutputFile)
 | 
						|
{
 | 
						|
  Node* tree1 = Node::ReadTree(aInputFile);
 | 
						|
  if (nullptr != tree1) {
 | 
						|
    DumpTree(tree1, aOutputFile, 0);
 | 
						|
    Node::Destroy(tree1);
 | 
						|
    return NS_OK;
 | 
						|
  }
 | 
						|
  return NS_ERROR_FAILURE;
 | 
						|
}
 | 
						|
#endif
 |