nsresult
SVGTransformListParser::MatchScale()
{
  GetNextToken();

  float s[2];
  PRUint32 count;

  ENSURE_MATCHED(MatchNumberArguments(s, NS_ARRAY_LENGTH(s), &count));

  switch (count) {
    case 1:
      s[1] = s[0];
      // fall-through
    case 2:
    {
      SVGTransform* transform = mTransforms.AppendElement();
      NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
      transform->SetScale(s[0], s[1]);
      break;
    }
    default:
      return NS_ERROR_FAILURE;
  }

  return NS_OK;
}
already_AddRefed<SVGTransform>
DOMSVGTransformList::ReplaceItem(SVGTransform& newItem,
                                 uint32_t index, ErrorResult& error)
{
  if (IsAnimValList()) {
    error.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
    return nullptr;
  }

  if (index >= LengthNoFlush()) {
    error.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
    return nullptr;
  }

  nsRefPtr<SVGTransform> domItem = &newItem;
  if (newItem.HasOwner()) {
    domItem = newItem.Clone(); // must do this before changing anything!
  }

  AutoChangeTransformListNotifier notifier(this);
  if (mItems[index]) {
    // Notify any existing DOM item of removal *before* modifying the lists so
    // that the DOM item can copy the *old* value at its index:
    mItems[index]->RemovingFromList();
  }

  InternalList()[index] = domItem->ToSVGTransform();
  mItems[index] = domItem;

  // This MUST come after the ToSVGPoint() call, otherwise that call
  // would end up reading bad data from InternalList()!
  domItem->InsertingIntoList(this, index, IsAnimValList());

  return domItem.forget();
}
nsresult
SVGTransformListParser::MatchRotate()
{
  GetNextToken();

  float r[3];
  PRUint32 count;

  ENSURE_MATCHED(MatchNumberArguments(r, NS_ARRAY_LENGTH(r), &count));

  switch (count) {
    case 1:
      r[1] = r[2] = 0.f;
      // fall-through
    case 3:
    {
      SVGTransform* transform = mTransforms.AppendElement();
      NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
      transform->SetRotate(r[0], r[1], r[2]);
      break;
    }
    default:
      return NS_ERROR_FAILURE;
  }

  return NS_OK;
}
nsresult
SVGTransformListParser::MatchTranslate()
{
  GetNextToken();

  float t[2];
  uint32_t count;

  ENSURE_MATCHED(MatchNumberArguments(t, ArrayLength(t), &count));

  switch (count) {
    case 1:
      t[1] = 0.f;
      // fall-through
    case 2:
    {
      SVGTransform* transform = mTransforms.AppendElement();
      NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
      transform->SetTranslate(t[0], t[1]);
      break;
    }
    default:
      return NS_ERROR_FAILURE;
  }

  return NS_OK;
}
String SVGTransformList::valueAsString() const
{
    // TODO: We may want to build a real transform string, instead of concatting to a matrix(...).
    SVGTransform transform = concatenate();
    if (transform.type() == SVGTransform::SVG_TRANSFORM_MATRIX) {
        TransformationMatrix matrix = transform.matrix();
        return String::format("matrix(%f %f %f %f %f %f)", matrix.a(), matrix.b(), matrix.c(), matrix.d(), matrix.e(), matrix.f());
    }

    return String();
}
already_AddRefed<SVGTransform>
DOMSVGTransformList::Initialize(SVGTransform& newItem, ErrorResult& error)
{
  if (IsAnimValList()) {
    error.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
    return nullptr;
  }

  // If newItem is already in a list we should insert a clone of newItem, and
  // for consistency, this should happen even if *this* is the list that
  // newItem is currently in. Note that in the case of newItem being in this
  // list, the Clear() call before the InsertItemBefore() call would remove it
  // from this list, and so the InsertItemBefore() call would not insert a
  // clone of newItem, it would actually insert newItem. To prevent that from
  // happening we have to do the clone here, if necessary.

  nsRefPtr<SVGTransform> domItem = &newItem;
  if (domItem->HasOwner()) {
    domItem = newItem.Clone();
  }

  Clear(error);
  MOZ_ASSERT(!error.Failed(), "How could this fail?");
  return InsertItemBefore(*domItem, 0, error);
}
already_AddRefed<SVGTransform>
DOMSVGTransformList::InsertItemBefore(SVGTransform& newItem,
                                      uint32_t index, ErrorResult& error)
{
  if (IsAnimValList()) {
    error.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
    return nullptr;
  }

  index = std::min(index, LengthNoFlush());
  if (index >= SVGTransform::MaxListIndex()) {
    error.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
    return nullptr;
  }

  nsRefPtr<SVGTransform> domItem = &newItem;
  if (newItem.HasOwner()) {
    domItem = newItem.Clone(); // must do this before changing anything!
  }

  // Ensure we have enough memory so we can avoid complex error handling below:
  if (!mItems.SetCapacity(mItems.Length() + 1) ||
      !InternalList().SetCapacity(InternalList().Length() + 1)) {
    error.Throw(NS_ERROR_OUT_OF_MEMORY);
    return nullptr;
  }

  nsAttrValue emptyOrOldValue = Element()->WillChangeTransformList();
  // Now that we know we're inserting, keep animVal list in sync as necessary.
  MaybeInsertNullInAnimValListAt(index);

  InternalList().InsertItem(index, domItem->ToSVGTransform());
  mItems.InsertElementAt(index, domItem.get());

  // This MUST come after the insertion into InternalList(), or else under the
  // insertion into InternalList() the values read from domItem would be bad
  // data from InternalList() itself!:
  domItem->InsertingIntoList(this, index, IsAnimValList());

  UpdateListIndicesFromIndex(mItems, index + 1);

  Element()->DidChangeTransformList(emptyOrOldValue);
  if (mAList->IsAnimating()) {
    Element()->AnimationNeedsResample();
  }
  return domItem.forget();
}
nsresult
SVGTransformListParser::MatchMatrix()
{
  GetNextToken();

  float m[6];
  PRUint32 count;

  ENSURE_MATCHED(MatchNumberArguments(m, NS_ARRAY_LENGTH(m), &count));

  if (count != 6) {
    return NS_ERROR_FAILURE;
  }

  SVGTransform* transform = mTransforms.AppendElement();
  NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
  transform->SetMatrix(gfxMatrix(m[0], m[1], m[2], m[3], m[4], m[5]));

  return NS_OK;
}
nsresult
SVGTransformListParser::MatchSkewY()
{
  GetNextToken();

  float skew;
  PRUint32 count;

  ENSURE_MATCHED(MatchNumberArguments(&skew, 1, &count));

  if (count != 1) {
    return NS_ERROR_FAILURE;
  }

  SVGTransform* transform = mTransforms.AppendElement();
  NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
  transform->SetSkewY(skew);

  return NS_OK;
}
Beispiel #10
0
bool SVGTransformable::parseTransformValue(SVGTransform::SVGTransformType type, const UChar*& ptr, const UChar* end, SVGTransform& transform)
{
    if (type == SVGTransform::SVG_TRANSFORM_UNKNOWN)
        return false;

    int valueCount = 0;
    float values[] = {0, 0, 0, 0, 0, 0};
    if ((valueCount = parseTransformParamList(ptr, end, values, requiredValuesForType[type], optionalValuesForType[type])) < 0)
        return false;

    switch (type) {
    case SVGTransform::SVG_TRANSFORM_UNKNOWN:
        ASSERT_NOT_REACHED();
        break;
    case SVGTransform::SVG_TRANSFORM_SKEWX:
        transform.setSkewX(values[0]);
        break;
    case SVGTransform::SVG_TRANSFORM_SKEWY:
        transform.setSkewY(values[0]);
        break;
    case SVGTransform::SVG_TRANSFORM_SCALE:
        if (valueCount == 1) // Spec: if only one param given, assume uniform scaling
            transform.setScale(values[0], values[0]);
        else
            transform.setScale(values[0], values[1]);
        break;
    case SVGTransform::SVG_TRANSFORM_TRANSLATE:
        if (valueCount == 1) // Spec: if only one param given, assume 2nd param to be 0
            transform.setTranslate(values[0], 0);
        else
            transform.setTranslate(values[0], values[1]);
        break;
    case SVGTransform::SVG_TRANSFORM_ROTATE:
        if (valueCount == 1)
            transform.setRotate(values[0], 0, 0);
        else
            transform.setRotate(values[0], values[1], values[2]);
        break;
    case SVGTransform::SVG_TRANSFORM_MATRIX:
        transform.setMatrix(AffineTransform(values[0], values[1], values[2], values[3], values[4], values[5]));
        break;
    }

    return true;
}
SVGTransform SVGTransformDistance::addToSVGTransform(const SVGTransform& transform) const
{
    ASSERT(m_type == transform.type() || transform == SVGTransform());
    
    SVGTransform newTransform(transform);
    
    switch (m_type) {
    case SVGTransform::SVG_TRANSFORM_UNKNOWN:
        return SVGTransform();
    case SVGTransform::SVG_TRANSFORM_MATRIX:
        return SVGTransform(transform.matrix() * m_transform);
    case SVGTransform::SVG_TRANSFORM_TRANSLATE:
    {
        FloatPoint translation = transform.translate();
        translation += FloatSize::narrowPrecision(m_transform.e(), m_transform.f());
        newTransform.setTranslate(translation.x(), translation.y());
        return newTransform;
    }
    case SVGTransform::SVG_TRANSFORM_SCALE:
    {
        FloatSize scale = transform.scale();
        scale += FloatSize::narrowPrecision(m_transform.a(), m_transform.d());
        newTransform.setScale(scale.width(), scale.height());
        return newTransform;
    }
    case SVGTransform::SVG_TRANSFORM_ROTATE:
    {
        // FIXME: I'm not certain the translation is calculated correctly here
        FloatPoint center = transform.rotationCenter();
        newTransform.setRotate(transform.angle() + m_angle,
                               center.x() + m_cx,
                               center.y() + m_cy);
        return newTransform;
    }
    case SVGTransform::SVG_TRANSFORM_SKEWX:
        newTransform.setSkewX(transform.angle() + m_angle);
        return newTransform;
    case SVGTransform::SVG_TRANSFORM_SKEWY:
        newTransform.setSkewY(transform.angle() + m_angle);
        return newTransform;
    }
    
    ASSERT_NOT_REACHED();
    return SVGTransform();
}
SVGTransform* SVGTransformDistance::addSVGTransforms(SVGTransform* first,
                                                     SVGTransform* second,
                                                     unsigned repeatCount) {
  ASSERT(first->transformType() == second->transformType());

  SVGTransform* transform = SVGTransform::create();

  switch (first->transformType()) {
    case kSvgTransformMatrix:
      ASSERT_NOT_REACHED();
    case kSvgTransformUnknown:
      return transform;
    case kSvgTransformRotate: {
      transform->setRotate(first->angle() + second->angle() * repeatCount,
                           first->rotationCenter().x() +
                               second->rotationCenter().x() * repeatCount,
                           first->rotationCenter().y() +
                               second->rotationCenter().y() * repeatCount);
      return transform;
    }
    case kSvgTransformTranslate: {
      float dx = first->translate().x() + second->translate().x() * repeatCount;
      float dy = first->translate().y() + second->translate().y() * repeatCount;
      transform->setTranslate(dx, dy);
      return transform;
    }
    case kSvgTransformScale: {
      FloatSize scale = second->scale();
      scale.scale(repeatCount);
      scale += first->scale();
      transform->setScale(scale.width(), scale.height());
      return transform;
    }
    case kSvgTransformSkewx:
      transform->setSkewX(first->angle() + second->angle() * repeatCount);
      return transform;
    case kSvgTransformSkewy:
      transform->setSkewY(first->angle() + second->angle() * repeatCount);
      return transform;
  }
  ASSERT_NOT_REACHED();
  return transform;
}
SVGTransform* SVGTransformDistance::addToSVGTransform(
    SVGTransform* transform) const {
  DCHECK(m_transformType == transform->transformType() ||
         m_transformType == kSvgTransformUnknown);

  SVGTransform* newTransform = transform->clone();

  switch (m_transformType) {
    case kSvgTransformMatrix:
      ASSERT_NOT_REACHED();
    case kSvgTransformUnknown:
      return SVGTransform::create();
    case kSvgTransformTranslate: {
      FloatPoint translation = transform->translate();
      translation +=
          FloatSize::narrowPrecision(m_transform.e(), m_transform.f());
      newTransform->setTranslate(translation.x(), translation.y());
      return newTransform;
    }
    case kSvgTransformScale: {
      FloatSize scale = transform->scale();
      scale += FloatSize::narrowPrecision(m_transform.a(), m_transform.d());
      newTransform->setScale(scale.width(), scale.height());
      return newTransform;
    }
    case kSvgTransformRotate: {
      FloatPoint center = transform->rotationCenter();
      newTransform->setRotate(transform->angle() + m_angle, center.x() + m_cx,
                              center.y() + m_cy);
      return newTransform;
    }
    case kSvgTransformSkewx:
      newTransform->setSkewX(transform->angle() + m_angle);
      return newTransform;
    case kSvgTransformSkewy:
      newTransform->setSkewY(transform->angle() + m_angle);
      return newTransform;
  }

  ASSERT_NOT_REACHED();
  return newTransform;
}
Beispiel #14
0
SVGTransform *SVGSVGElement::createSVGTransformFromMatrix(SVGMatrix *matrix)
{    
    SVGTransform *obj = SVGSVGElement::createSVGTransform();
    obj->setMatrix(matrix);
    return obj;
}
Beispiel #15
0
bool SVGTransformable::parseTransformAttribute(SVGTransformList* list, const AtomicString& transform)
{
    double x[] = {0, 0, 0, 0, 0, 0};
    int nr = 0, required = 0, optional = 0;
    
    const UChar* currTransform = transform.characters();
    const UChar* end = currTransform + transform.length();

    bool delimParsed = false;
    while (currTransform < end) {
        delimParsed = false;
        unsigned short type = SVGTransform::SVG_TRANSFORM_UNKNOWN;
        skipOptionalSpaces(currTransform, end);
        
        if (currTransform >= end)
            return false;
        
        if (*currTransform == 's') {
            if (skipString(currTransform, end, skewXDesc, sizeof(skewXDesc) / sizeof(UChar))) {
                required = 1;
                optional = 0;
                type = SVGTransform::SVG_TRANSFORM_SKEWX;
            } else if (skipString(currTransform, end, skewYDesc, sizeof(skewYDesc) / sizeof(UChar))) {
                required = 1;
                optional = 0;
                type = SVGTransform::SVG_TRANSFORM_SKEWY;
            } else if (skipString(currTransform, end, scaleDesc, sizeof(scaleDesc) / sizeof(UChar))) {
                required = 1;
                optional = 1;
                type = SVGTransform::SVG_TRANSFORM_SCALE;
            } else
                return false;
        } else if (skipString(currTransform, end, translateDesc, sizeof(translateDesc) / sizeof(UChar))) {
            required = 1;
            optional = 1;
            type = SVGTransform::SVG_TRANSFORM_TRANSLATE;
        } else if (skipString(currTransform, end, rotateDesc, sizeof(rotateDesc) / sizeof(UChar))) {
            required = 1;
            optional = 2;
            type = SVGTransform::SVG_TRANSFORM_ROTATE;
        } else if (skipString(currTransform, end, matrixDesc, sizeof(matrixDesc) / sizeof(UChar))) {
            required = 6;
            optional = 0;
            type = SVGTransform::SVG_TRANSFORM_MATRIX;
        } else 
            return false;

        if ((nr = parseTransformParamList(currTransform, end, x, required, optional)) < 0)
            return false;

        SVGTransform t;

        switch (type) {
            case SVGTransform::SVG_TRANSFORM_SKEWX:
               t.setSkewX(narrowPrecisionToFloat(x[0]));
                break;
            case SVGTransform::SVG_TRANSFORM_SKEWY:
               t.setSkewY(narrowPrecisionToFloat(x[0]));
                break;
            case SVGTransform::SVG_TRANSFORM_SCALE:
                  if (nr == 1) // Spec: if only one param given, assume uniform scaling
                      t.setScale(narrowPrecisionToFloat(x[0]), narrowPrecisionToFloat(x[0]));
                  else
                      t.setScale(narrowPrecisionToFloat(x[0]), narrowPrecisionToFloat(x[1]));
                break;
            case SVGTransform::SVG_TRANSFORM_TRANSLATE:
                  if (nr == 1) // Spec: if only one param given, assume 2nd param to be 0
                      t.setTranslate(narrowPrecisionToFloat(x[0]), 0);
                  else
                      t.setTranslate(narrowPrecisionToFloat(x[0]), narrowPrecisionToFloat(x[1]));
                break;
            case SVGTransform::SVG_TRANSFORM_ROTATE:
                  if (nr == 1)
                      t.setRotate(narrowPrecisionToFloat(x[0]), 0, 0);
                  else
                      t.setRotate(narrowPrecisionToFloat(x[0]), narrowPrecisionToFloat(x[1]), narrowPrecisionToFloat(x[2]));
                break;
            case SVGTransform::SVG_TRANSFORM_MATRIX:
                t.setMatrix(AffineTransform(x[0], x[1], x[2], x[3], x[4], x[5]));
                break;
        }

        ExceptionCode ec = 0;
        list->appendItem(t, ec);
        skipOptionalSpaces(currTransform, end);
        if (currTransform < end && *currTransform == ',') {
            delimParsed = true;
            currTransform++;
        }
        skipOptionalSpaces(currTransform, end);
    }

    return !delimParsed;
}
Beispiel #16
0
float SVGAnimateTransformElement::calculateDistance(const String& fromString, const String& toString)
{
    // FIXME: This is not correct in all cases. The spec demands that each component (translate x and y for example) 
    // is paced separately. To implement this we need to treat each component as individual animation everywhere.
    SVGTransform from = parseTransformValue(fromString);
    if (!from.isValid())
        return -1.f;
    SVGTransform to = parseTransformValue(toString);
    if (!to.isValid() || from.type() != to.type())
        return -1.f;
    if (to.type() == SVGTransform::SVG_TRANSFORM_TRANSLATE) {
        FloatSize diff = to.translate() - from.translate();
        return sqrtf(diff.width() * diff.width() + diff.height() * diff.height());
    }
    if (to.type() == SVGTransform::SVG_TRANSFORM_ROTATE)
        return fabsf(to.angle() - from.angle());
    if (to.type() == SVGTransform::SVG_TRANSFORM_SCALE) {
        FloatSize diff = to.scale() - from.scale();
        return sqrtf(diff.width() * diff.width() + diff.height() * diff.height());
    }
    return -1.f;
}
SVGTransformDistance::SVGTransformDistance(const SVGTransform& fromSVGTransform, const SVGTransform& toSVGTransform)
    : m_type(fromSVGTransform.type())
    , m_angle(0)
    , m_cx(0)
    , m_cy(0)
{
    ASSERT(m_type == toSVGTransform.type());
    
    switch (m_type) {
    case SVGTransform::SVG_TRANSFORM_UNKNOWN:
        return;
    case SVGTransform::SVG_TRANSFORM_MATRIX:
        // FIXME: need to be able to subtract to matrices
        return;
    case SVGTransform::SVG_TRANSFORM_ROTATE:
    {
        FloatSize centerDistance = toSVGTransform.rotationCenter() - fromSVGTransform.rotationCenter();
        m_angle = toSVGTransform.angle() - fromSVGTransform.angle();
        m_cx = centerDistance.width();
        m_cy = centerDistance.height();
        return;
    }
    case SVGTransform::SVG_TRANSFORM_TRANSLATE:
    {
        FloatSize translationDistance = toSVGTransform.translate() - fromSVGTransform.translate();
        m_transform.translate(translationDistance.width(), translationDistance.height());
        return;
    }
    case SVGTransform::SVG_TRANSFORM_SCALE:
    {
        float scaleX = toSVGTransform.scale().width() - fromSVGTransform.scale().width();        
        float scaleY = toSVGTransform.scale().height() - fromSVGTransform.scale().height();
        m_transform.scaleNonUniform(scaleX, scaleY);
        return;
    }
    case SVGTransform::SVG_TRANSFORM_SKEWX:
    case SVGTransform::SVG_TRANSFORM_SKEWY:
        m_angle = toSVGTransform.angle() - fromSVGTransform.angle();
        return;
    }
}
void SVGTransformDistance::addSVGTransform(const SVGTransform& transform, bool absoluteValue)
{
    // If this is the first add, set the type for this SVGTransformDistance
    if (m_type == SVGTransform::SVG_TRANSFORM_UNKNOWN)
        m_type = transform.type();
    
    ASSERT(m_type == transform.type());
    
    switch (m_type) {
    case SVGTransform::SVG_TRANSFORM_UNKNOWN:
        return;
    case SVGTransform::SVG_TRANSFORM_MATRIX:
        m_transform *= transform.matrix(); // FIXME: what does 'distance' between two transforms mean?  how should we respect 'absoluteValue' here?
        return;
    case SVGTransform::SVG_TRANSFORM_ROTATE:
        m_angle += absoluteValue ? fabsf(transform.angle()) : transform.angle();
        m_cx += absoluteValue ? fabsf(transform.rotationCenter().x()) : transform.rotationCenter().x();
        m_cy += absoluteValue ? fabsf(transform.rotationCenter().y()) : transform.rotationCenter().y();
        // fall through
    case SVGTransform::SVG_TRANSFORM_TRANSLATE:
    {
        float dx = absoluteValue ? fabsf(transform.translate().x()) : transform.translate().x();
        float dy = absoluteValue ? fabsf(transform.translate().y()) : transform.translate().y();
        m_transform.translate(dx, dy);
        return;
    }
    case SVGTransform::SVG_TRANSFORM_SCALE:
    {
        float scaleX = absoluteValue ? fabsf(transform.scale().width()) : transform.scale().width();
        float scaleY = absoluteValue ? fabsf(transform.scale().height()) : transform.scale().height();
        m_transform.scaleNonUniform(scaleX, scaleY);
        return;
    }
    case SVGTransform::SVG_TRANSFORM_SKEWX:
    case SVGTransform::SVG_TRANSFORM_SKEWY:
        m_angle += absoluteValue ? fabsf(transform.angle()) : transform.angle();
        return;
    }
    
    ASSERT_NOT_REACHED();
    return;
}
SVGTransform SVGTransformDistance::addSVGTransforms(const SVGTransform& first, const SVGTransform& second)
{
    ASSERT(first.type() == second.type());
    
    SVGTransform transform;
    
    switch (first.type()) {
    case SVGTransform::SVG_TRANSFORM_UNKNOWN:
        return SVGTransform();
    case SVGTransform::SVG_TRANSFORM_ROTATE:
    {
        transform.setRotate(first.angle() + second.angle(), first.rotationCenter().x() + second.rotationCenter().x(),
                            first.rotationCenter().y() + second.rotationCenter().y());
        return transform;
    }
    case SVGTransform::SVG_TRANSFORM_MATRIX:
        transform.setMatrix(first.matrix() * second.matrix());
        return transform;
    case SVGTransform::SVG_TRANSFORM_TRANSLATE:
    {
        float dx = first.translate().x() + second.translate().x();
        float dy = first.translate().y() + second.translate().y();
        transform.setTranslate(dx, dy);
        return transform;
    }
    case SVGTransform::SVG_TRANSFORM_SCALE:
    {
        FloatSize scale = first.scale() + second.scale();
        transform.setScale(scale.width(), scale.height());
        return transform;
    }
    case SVGTransform::SVG_TRANSFORM_SKEWX:
        transform.setSkewX(first.angle() + second.angle());
        return transform;
    case SVGTransform::SVG_TRANSFORM_SKEWY:
        transform.setSkewY(first.angle() + second.angle());
        return transform;
    }
    
    ASSERT_NOT_REACHED();
    return SVGTransform();
}
void SVGTransformList::ParseTransform(StringIn s)
{

	if (s.IsEmpty()) return;

	ASSERT(0);
#if 0

	const WCHAR* p = s->c_str();
	if (p == NULL) THROW(std::exception("null pointer"));

	while (*p)
	{
		while (*p && std::isspace(*p)) p++;	// Skip spaces

		// Get type
		const WCHAR* transformType = p;
		int transformTypeLength = 0;

		while (*p && std::isalpha(*p))
		{
			transformTypeLength++;
			p++;
		}

		while (*p && std::isspace(*p)) p++;	// Skip spaces

	// Get string inside ( )
		if (*p++ != L'(') break;	// Error

		const WCHAR* start = p;
		while (*p && *p != L')')
		{
			p++;
		}
		System::StringW* param_string = new System::StringW(string_copy(start, p - start));

		if (*p++ != L')') break; // Error
		while (*p && std::isspace(*p)) p++;	// Skip spaces

		SVGTransform* transform = NULL;

#if WIN32
		if (!_wcsnicmp(transformType, L"translate", transformTypeLength))
		{
			double x, y;
			GetTranslateValues(param_string->c_str(), x, y);

			transform = new SVGTransformMutable;
			transform->SetTranslate(x, y);
		}
		else if (!_wcsnicmp(transformType, L"rotate", transformTypeLength))
		{
			double deg, cx, cy;
			GetRotateValues(param_string->c_str(), deg, cx, cy);

			transform = new SVGTransformMutable;
			transform->SetRotate(deg, cx, cy);
		}
		else if (!_wcsnicmp(transformType, L"scale", transformTypeLength))
		{
			double sx, sy;
			GetScaleValues(param_string->c_str(), sx, sy);

			transform = new SVGTransformMutable;
			transform->SetScale(sx, sy);
		}
		else if (!_wcsnicmp(transformType, L"skewX", transformTypeLength))
		{
			double deg;
			GetSkewValues(param_string->c_str(), deg);

			transform = new SVGTransformMutable;
			transform->SetSkewX(deg);
		}
		else if (!_wcsnicmp(transformType, L"skewY", transformTypeLength))
		{
			double deg;
			GetSkewValues(param_string->c_str(), deg);

			transform = new SVGTransformMutable;
			transform->SetSkewY(deg);
		}
		else if (!_wcsnicmp(transformType, L"matrix", transformTypeLength))
		{
			transform = new SVGTransformMutable;

			transform->m_type = SVG_TRANSFORM_MATRIX;
			GetMatrixValues(param_string->c_str(), transform->m_matrix);
		}
#else
		ASSERT(0);
#endif

		if (transform != NULL)
		{
			transform->m_owner = this;
		//	transform->m_pListener = this;
			m_p->m_items.Add(transform);
		}

		if (*p == ',') p++;
		while (*p && std::isspace(*p)) p++;	// Skip spaces
	}
#endif
}
String SVGTransformList::StringFromTransformList() const
{
	IO::StringWriter str;

	unsigned int numberOfItems = m_p->m_items.GetSize();

	for (size_t i = 0; i < numberOfItems; i++)
	{
		SVGTransform* transform = m_p->m_items[i];

		SVGTransformType type = transform->get_type();

		SVGMatrix* matrix = transform->get_matrix();

		double a = matrix->get_a();
		double b = matrix->get_b();
		double c = matrix->get_c();
		double d = matrix->get_d();
		double e = matrix->get_e();
		double f = matrix->get_f();

		if (i > 0) str << " ";

		switch (type)
		{
			case SVG_TRANSFORM_TRANSLATE:
			{
				str << "translate(" << e << "," << f << ")";
			}
			break;

			case SVG_TRANSFORM_SCALE:
			{
			//	swprintf(str2, OLESTR("scale(%g, %g)"), a, d);
			//	str += str2;
				str << "scale(" << a << "," << d << ")";
			}
			break;

			case SVG_TRANSFORM_ROTATE:
			{
				double angle = transform->get_angle();
			//	swprintf(str2, OLESTR("rotate(%g, %g, %g)"), angle, e, f);
			//	str += str2;
				str << "rotate(" << angle << "," << e << "," << f << ")";
			}
			break;

			case SVG_TRANSFORM_SKEWX:
			{
				double angle = transform->get_angle();
		//		swprintf(str2, OLESTR("skewX(%g)"), angle);
		//		str += str2;
				str << "skewX(" << angle << ")";
			}
			break;

			case SVG_TRANSFORM_SKEWY:
			{
				double angle = transform->get_angle();
			//	swprintf(str2, OLESTR("skewY(%g)"), angle);
			//	str += str2;
				str << "skewY(" << angle << ")";
			}
			break;

			case SVG_TRANSFORM_MATRIX:
			{
			//	swprintf(str2, OLESTR("matrix(%g %g %g %g %g %g)"), a, b, c, d, e, f);
			//	str += str2;
				str << "matrix(" << a << "," << b << "," << c << "," << d << "," << e << "," << f << ")";
			}
			break;

			default:
				ASSERT(0);
		}
	}

	return str.str();
}
Beispiel #22
0
SVGTransformDistance::SVGTransformDistance(const SVGTransform& fromSVGTransform, const SVGTransform& toSVGTransform)
    : m_type(fromSVGTransform.type())
    , m_angle(0)
    , m_cx(0)
    , m_cy(0)
{
    ASSERT(m_type == toSVGTransform.type());
    
    switch (m_type) {
    case SVGTransform::SVG_TRANSFORM_MATRIX:
        ASSERT_NOT_REACHED();
    case SVGTransform::SVG_TRANSFORM_UNKNOWN:
        break;
    case SVGTransform::SVG_TRANSFORM_ROTATE: {
        FloatSize centerDistance = toSVGTransform.rotationCenter() - fromSVGTransform.rotationCenter();
        m_angle = toSVGTransform.angle() - fromSVGTransform.angle();
        m_cx = centerDistance.width();
        m_cy = centerDistance.height();
        break;
    }
    case SVGTransform::SVG_TRANSFORM_TRANSLATE: {
        FloatSize translationDistance = toSVGTransform.translate() - fromSVGTransform.translate();
        m_transform.translate(translationDistance.width(), translationDistance.height());
        break;
    }
    case SVGTransform::SVG_TRANSFORM_SCALE: {
        float scaleX = toSVGTransform.scale().width() - fromSVGTransform.scale().width();        
        float scaleY = toSVGTransform.scale().height() - fromSVGTransform.scale().height();
        m_transform.scaleNonUniform(scaleX, scaleY);
        break;
    }
    case SVGTransform::SVG_TRANSFORM_SKEWX:
    case SVGTransform::SVG_TRANSFORM_SKEWY:
        m_angle = toSVGTransform.angle() - fromSVGTransform.angle();
        break;
    }
}