void nsMathMLmmultiscriptsFrame::ProcessAttributes() { mSubScriptShift = 0; mSupScriptShift = 0; // check if the subscriptshift attribute is there nsAutoString value; GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::subscriptshift_, value); if (!value.IsEmpty()) { nsCSSValue cssValue; if (ParseNumericValue(value, cssValue) && cssValue.IsLengthUnit()) { mSubScriptShift = CalcLength(PresContext(), mStyleContext, cssValue); } } // check if the superscriptshift attribute is there GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::superscriptshift_, value); if (!value.IsEmpty()) { nsCSSValue cssValue; if (ParseNumericValue(value, cssValue) && cssValue.IsLengthUnit()) { mSupScriptShift = CalcLength(PresContext(), mStyleContext, cssValue); } } }
static void ProcessTranslatePart(float& aResult, const nsCSSValue& aValue, nsStyleContext* aContext, nsPresContext* aPresContext, PRBool& aCanStoreInRuleTree, nscoord aSize, float aAppUnitsPerMatrixUnit) { nscoord offset = 0; float percent = 0.0f; if (aValue.GetUnit() == eCSSUnit_Percent) { percent = aValue.GetPercentValue(); } else if (aValue.IsCalcUnit()) { nsRuleNode::ComputedCalc result = nsRuleNode::SpecifiedCalcToComputedCalc(aValue, aContext, aPresContext, aCanStoreInRuleTree); percent = result.mPercent; offset = result.mLength; } else { offset = CalcLength(aValue, aContext, aPresContext, aCanStoreInRuleTree); } aResult = (percent * NSAppUnitsToFloatPixels(aSize, aAppUnitsPerMatrixUnit)) + NSAppUnitsToFloatPixels(offset, aAppUnitsPerMatrixUnit); }
/* virtual */ nsresult nsMathMLmsupFrame::Place(nsRenderingContext& aRenderingContext, PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize) { // extra spacing after sup/subscript nscoord scriptSpace = nsPresContext::CSSPointsToAppUnits(0.5f); // 0.5pt as in plain TeX // check if the superscriptshift attribute is there nsAutoString value; nscoord supScriptShift = 0; GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::superscriptshift_, value); if (!value.IsEmpty()) { nsCSSValue cssValue; if (ParseNumericValue(value, cssValue) && cssValue.IsLengthUnit()) { supScriptShift = CalcLength(PresContext(), mStyleContext, cssValue); } } return nsMathMLmsupFrame::PlaceSuperScript(PresContext(), aRenderingContext, aPlaceOrigin, aDesiredSize, this, supScriptShift, scriptSpace); }
/* static */ void nsMathMLFrame::ParseNumericValue(const nsString& aString, nscoord* aLengthValue, uint32_t aFlags, nsPresContext* aPresContext, nsStyleContext* aStyleContext) { nsCSSValue cssValue; if (!nsMathMLElement::ParseNumericValue(aString, cssValue, aFlags, aPresContext->Document())) { // Invalid attribute value. aLengthValue remains unchanged, so the default // length value is used. return; } nsCSSUnit unit = cssValue.GetUnit(); if (unit == eCSSUnit_Percent || unit == eCSSUnit_Number) { // Relative units. A multiple of the default length value is used. *aLengthValue = NSToCoordRound(*aLengthValue * (unit == eCSSUnit_Percent ? cssValue.GetPercentValue() : cssValue.GetFloatValue())); return; } // Absolute units. *aLengthValue = CalcLength(aPresContext, aStyleContext, cssValue); }
void nsMathMLmspaceFrame::ProcessAttributes(nsPresContext* aPresContext) { /* parse the attributes width = number h-unit height = number v-unit depth = number v-unit */ nsAutoString value; nsCSSValue cssValue; // width mWidth = 0; if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, nsMathMLAtoms::width_, value)) { if ((ParseNumericValue(value, cssValue) || ParseNamedSpaceValue(mPresentationData.mstyle, value, cssValue)) && cssValue.IsLengthUnit()) { mWidth = CalcLength(aPresContext, mStyleContext, cssValue); } } // height mHeight = 0; if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, nsMathMLAtoms::height_, value)) { if ((ParseNumericValue(value, cssValue) || ParseNamedSpaceValue(mPresentationData.mstyle, value, cssValue)) && cssValue.IsLengthUnit()) { mHeight = CalcLength(aPresContext, mStyleContext, cssValue); } } // depth mDepth = 0; if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, nsMathMLAtoms::depth_, value)) { if ((ParseNumericValue(value, cssValue) || ParseNamedSpaceValue(mPresentationData.mstyle, value, cssValue)) && cssValue.IsLengthUnit()) { mDepth = CalcLength(aPresContext, mStyleContext, cssValue); } } }
///--------------------------------------------------------------------------------- /// very slow ///--------------------------------------------------------------------------------- void Vector2::RotateRadians( float radians ) { float length = CalcLength(); float headingInRadians = CalcHeadingRadians(); headingInRadians += radians; x = length * cos( headingInRadians ); y = length * sin( headingInRadians ); }
///--------------------------------------------------------------------------------- /// very slow ///--------------------------------------------------------------------------------- float Vector2::SetLength( float newLength ) { float oldLength = CalcLength(); Normalize(); x *= newLength; y *= newLength; return oldLength; }
///--------------------------------------------------------------------------------- /// very slow ///--------------------------------------------------------------------------------- void Vector2::RotateDegrees( float degrees ) { float length = CalcLength(); float headingInDegrees = CalcHeadingDegrees(); headingInDegrees += degrees; float headingInRadians = ConvertDegreesToRadians( headingInDegrees ); x = length * cos( headingInRadians ); y = length * sin( headingInRadians ); }
nscoord nsMathMLmfracFrame::CalcLineThickness(nsPresContext* aPresContext, nsStyleContext* aStyleContext, nsString& aThicknessAttribute, nscoord onePixel, nscoord aDefaultRuleThickness) { nscoord defaultThickness = aDefaultRuleThickness; nscoord lineThickness = aDefaultRuleThickness; nscoord minimumThickness = onePixel; if (!aThicknessAttribute.IsEmpty()) { if (aThicknessAttribute.EqualsLiteral("thin")) { lineThickness = NSToCoordFloor(defaultThickness * THIN_FRACTION_LINE); minimumThickness = onePixel * THIN_FRACTION_LINE_MINIMUM_PIXELS; // should visually decrease by at least one pixel, if default is not a pixel if (defaultThickness > onePixel && lineThickness > defaultThickness - onePixel) lineThickness = defaultThickness - onePixel; } else if (aThicknessAttribute.EqualsLiteral("medium")) { lineThickness = NSToCoordRound(defaultThickness * MEDIUM_FRACTION_LINE); minimumThickness = onePixel * MEDIUM_FRACTION_LINE_MINIMUM_PIXELS; // should visually increase by at least one pixel if (lineThickness < defaultThickness + onePixel) lineThickness = defaultThickness + onePixel; } else if (aThicknessAttribute.EqualsLiteral("thick")) { lineThickness = NSToCoordCeil(defaultThickness * THICK_FRACTION_LINE); minimumThickness = onePixel * THICK_FRACTION_LINE_MINIMUM_PIXELS; // should visually increase by at least two pixels if (lineThickness < defaultThickness + 2*onePixel) lineThickness = defaultThickness + 2*onePixel; } else { // see if it is a plain number, or a percentage, or a h/v-unit like 1ex, 2px, 1em nsCSSValue cssValue; if (ParseNumericValue(aThicknessAttribute, cssValue)) { nsCSSUnit unit = cssValue.GetUnit(); if (eCSSUnit_Number == unit) lineThickness = nscoord(float(defaultThickness) * cssValue.GetFloatValue()); else if (eCSSUnit_Percent == unit) lineThickness = nscoord(float(defaultThickness) * cssValue.GetPercentValue()); else if (eCSSUnit_Null != unit) lineThickness = CalcLength(aPresContext, aStyleContext, cssValue); } } } // use minimum if the lineThickness is a non-zero value less than minimun if (lineThickness && lineThickness < minimumThickness) lineThickness = minimumThickness; return lineThickness; }
primitiveType Vector4< primitiveType >::SetLength( primitiveType newLength ) { primitiveType oldLength = CalcLength(); Normalize4D(); x *= newLength; y *= newLength; z *= newLength; w *= newLength; return oldLength; }
void nsMathMLmpaddedFrame::UpdateValue(int32_t aSign, int32_t aPseudoUnit, const nsCSSValue& aCSSValue, const ReflowOutput& aDesiredSize, nscoord& aValueToUpdate, float aFontSizeInflation) const { nsCSSUnit unit = aCSSValue.GetUnit(); if (NS_MATHML_SIGN_INVALID != aSign && eCSSUnit_Null != unit) { nscoord scaler = 0, amount = 0; if (eCSSUnit_Percent == unit || eCSSUnit_Number == unit) { switch(aPseudoUnit) { case NS_MATHML_PSEUDO_UNIT_WIDTH: scaler = aDesiredSize.Width(); break; case NS_MATHML_PSEUDO_UNIT_HEIGHT: scaler = aDesiredSize.BlockStartAscent(); break; case NS_MATHML_PSEUDO_UNIT_DEPTH: scaler = aDesiredSize.Height() - aDesiredSize.BlockStartAscent(); break; default: // if we ever reach here, it would mean something is wrong // somewhere with the setup and/or the caller NS_ERROR("Unexpected Pseudo Unit"); return; } } if (eCSSUnit_Number == unit) amount = NSToCoordRound(float(scaler) * aCSSValue.GetFloatValue()); else if (eCSSUnit_Percent == unit) amount = NSToCoordRound(float(scaler) * aCSSValue.GetPercentValue()); else amount = CalcLength(PresContext(), mStyleContext, aCSSValue, aFontSizeInflation); if (NS_MATHML_SIGN_PLUS == aSign) aValueToUpdate += amount; else if (NS_MATHML_SIGN_MINUS == aSign) aValueToUpdate -= amount; else aValueToUpdate = amount; } }
void nsMathMLmpaddedFrame::UpdateValue(PRInt32 aSign, PRInt32 aPseudoUnit, const nsCSSValue& aCSSValue, const nsBoundingMetrics& aBoundingMetrics, nscoord& aValueToUpdate) const { nsCSSUnit unit = aCSSValue.GetUnit(); if (NS_MATHML_SIGN_INVALID != aSign && eCSSUnit_Null != unit) { nscoord scaler = 0, amount = 0; if (eCSSUnit_Percent == unit || eCSSUnit_Number == unit) { switch(aPseudoUnit) { case NS_MATHML_PSEUDO_UNIT_WIDTH: scaler = aBoundingMetrics.width; break; case NS_MATHML_PSEUDO_UNIT_HEIGHT: scaler = aBoundingMetrics.ascent; break; case NS_MATHML_PSEUDO_UNIT_DEPTH: scaler = aBoundingMetrics.descent; break; default: // if we ever reach here, it would mean something is wrong // somewhere with the setup and/or the caller NS_ERROR("Unexpected Pseudo Unit"); return; } } if (eCSSUnit_Number == unit) amount = NSToCoordRound(float(scaler) * aCSSValue.GetFloatValue()); else if (eCSSUnit_Percent == unit) amount = NSToCoordRound(float(scaler) * aCSSValue.GetPercentValue()); else amount = CalcLength(PresContext(), mStyleContext, aCSSValue); nscoord oldValue = aValueToUpdate; if (NS_MATHML_SIGN_PLUS == aSign) aValueToUpdate += amount; else if (NS_MATHML_SIGN_MINUS == aSign) aValueToUpdate -= amount; else aValueToUpdate = amount; } }
///--------------------------------------------------------------------------------- /// very slow ///--------------------------------------------------------------------------------- float Vector2::Normalize() { if( CalcLengthSquared() == 0.0f ) return 0.0f; float length = CalcLength(); if( length == 0.0f ) return 0.0f; float inverseLength = 1.0f / length; x *= inverseLength; y *= inverseLength; return length; }
primitiveType Vector4< primitiveType >::Normalize3D() { if( CalcLengthSquared() == (primitiveType) 0 ) return (primitiveType) 0; float length = CalcLength(); if( length == (primitiveType) 0 ) return (primitiveType) 0; float inverseLength = ( (primitiveType) 1 ) / length; x *= inverseLength; y *= inverseLength; z *= inverseLength; return length; }
///--------------------------------------------------------------------------------- /// ///--------------------------------------------------------------------------------- const Vector2 Vector2::Normalized() const { if (CalcLengthSquared() == 0.0f) return Vector2::ZERO; float length = CalcLength(); if (length == 0.0f) return Vector2::ZERO; Vector2 returnVec; float inverseLength = 1.0f / length; returnVec.x = x * inverseLength; returnVec.y = y * inverseLength; return returnVec; }
PWCHAR WSTR::New(PWCHAR Source, DWORD Len) { // Функция создаёт строку , копию Source. // Len - Количество копируемых символов // если равно 0, то будет скопирована вся строка if (Source == NULL) return NULL; if (Len == 0) Len = CalcLength(Source); if (Len == 0) return NULL; PWCHAR Str = Alloc(Len); if (Str != NULL) m_memcpy(Str, Source, Len * sizeof(WCHAR)); return Str; }
void nsMathMLmpaddedFrame::UpdateValue(PRInt32 aSign, PRInt32 aPseudoUnit, const nsCSSValue& aCSSValue, nscoord aLeftSpace, const nsBoundingMetrics& aBoundingMetrics, nscoord& aValueToUpdate) const { nsCSSUnit unit = aCSSValue.GetUnit(); if (NS_MATHML_SIGN_INVALID != aSign && eCSSUnit_Null != unit) { nscoord scaler = 0, amount = 0; if (eCSSUnit_Percent == unit || eCSSUnit_Number == unit) { switch(aPseudoUnit) { case NS_MATHML_PSEUDO_UNIT_WIDTH: scaler = aBoundingMetrics.width; break; case NS_MATHML_PSEUDO_UNIT_HEIGHT: scaler = aBoundingMetrics.ascent; break; case NS_MATHML_PSEUDO_UNIT_DEPTH: scaler = aBoundingMetrics.descent; break; case NS_MATHML_PSEUDO_UNIT_LSPACE: scaler = aLeftSpace; break; default: // if we ever reach here, it would mean something is wrong // somewhere with the setup and/or the caller NS_ASSERTION(0, "Unexpected Pseudo Unit"); return; } } if (eCSSUnit_Number == unit) amount = NSToCoordRound(float(scaler) * aCSSValue.GetFloatValue()); else if (eCSSUnit_Percent == unit) amount = NSToCoordRound(float(scaler) * aCSSValue.GetPercentValue()); else amount = CalcLength(PresContext(), mStyleContext, aCSSValue); nscoord oldValue = aValueToUpdate; if (NS_MATHML_SIGN_PLUS == aSign) aValueToUpdate += amount; else if (NS_MATHML_SIGN_MINUS == aSign) aValueToUpdate -= amount; else aValueToUpdate = amount; /* The REC says: Dimensions that would be positive if the content was rendered normally cannot be made negative using <mpadded>; a positive dimension is set to 0 if it would otherwise become negative. Dimensions which are initially 0 can be made negative */ if (0 < oldValue && 0 > aValueToUpdate) aValueToUpdate = 0; } }
void CMine::EditGeoBack() { vms_vector center,opp_center; double x,y,z,radius; int i; /* calculate center of current side */ center.x = center.y = center.z = 0; for (i = 0; i < 4; i++) { int vertnum = Segments (Current ()->segment)->verts [side_vert [Current ()->side][i]]; center.x += Vertices (vertnum)->x; center.y += Vertices (vertnum)->y; center.z += Vertices (vertnum)->z; } center.x /= 4; center.y /= 4; center.z /= 4; // calculate center of oppisite current side opp_center.x = opp_center.y = opp_center.z = 0; for (i = 0; i < 4; i++) { int vertnum = Segments (Current ()->segment)->verts [opp_side_vert [Current ()->side][i]]; opp_center.x += Vertices (vertnum)->x; opp_center.y += Vertices (vertnum)->y; opp_center.z += Vertices (vertnum)->z; } opp_center.x /= 4; opp_center.y /= 4; opp_center.z /= 4; // normalize vector x = center.x - opp_center.x; y = center.y - opp_center.y; z = center.z - opp_center.z; // make sure distance is positive to prevent // cube from turning inside out #if 1 // defines line orthogonal to a side at a point UINT8 orthog_line [6][4] = { {8,6,1,3}, {0,5,7,2}, {3,1,6,8}, {2,7,5,0}, {4,9,10,11}, {11,10,9,4} }; CDSegment *seg; INT16 point0,point1; vms_vector *vector0,*vector1; bool ok_to_move; ok_to_move = TRUE; seg = Segments () + Current ()->segment; switch (m_selectMode) { case POINT_MODE: point0 = line_vert [orthog_line [Current ()->side][Current ()->point]][0]; point1 = line_vert [orthog_line [Current ()->side][Current ()->point]][1]; vector0 = Vertices (seg->verts [point0]); vector1 = Vertices (seg->verts [point1]); if (CalcLength(vector0,vector1) - move_rate < F1_0 / 4) { ok_to_move = FALSE; } break; case LINE_MODE: for (i=0;i<2;i++) { point0 = line_vert [orthog_line [Current ()->side][(Current ()->line+i)%4]][0]; point1 = line_vert [orthog_line [Current ()->side][(Current ()->line+i)%4]][1]; vector0 = Vertices (seg->verts [point0]); vector1 = Vertices (seg->verts [point1]); if (CalcLength(vector0,vector1) - move_rate < F1_0 / 4) { ok_to_move = FALSE; } } break; case SIDE_MODE: for (i = 0; i < 4; i++) { point0 = line_vert [orthog_line [Current ()->side][i]][0]; point1 = line_vert [orthog_line [Current ()->side][i]][1]; vector0 = Vertices (seg->verts [point0]); vector1 = Vertices (seg->verts [point1]); if (CalcLength(vector0,vector1) - move_rate < F1_0 / 4) { ok_to_move = FALSE; } } break; } if (ok_to_move == FALSE) { ErrorMsg("Too small to move in that direction"); return; } #endif radius = sqrt(x*x + y*y + z*z); if ((radius-move_rate) < F1_0 / 4) { if (m_selectMode == POINT_MODE || m_selectMode == LINE_MODE || m_selectMode == SIDE_MODE) { ErrorMsg("Cannot make cube any smaller\n" "Cube must be greater or equal to 1.0 units wide."); } } else { // normalize direction if (radius > (F1_0/10)) { x /= radius; y /= radius; z /= radius; } else { vms_vector direction; CalcOrthoVector(direction,Current ()->segment,Current ()->side); x = (double)direction.x/(double)F1_0; y = (double)direction.y/(double)F1_0; z = (double)direction.z/(double)F1_0; } // move on x, y, and z theApp.SetModified (TRUE); theApp.LockUndo (); MoveOn('X',(INT32) (-x*move_rate)); MoveOn('Y',(INT32) (-y*move_rate)); MoveOn('Z',(INT32) (-z*move_rate)); theApp.UnlockUndo (); } theApp.SetModified (TRUE); }
void CMine::MovePoints(int pt0, int pt1) { vms_vector *vector0,*vector1,delta; int point0,point1; double length; int point; int i; vms_vector *vect; point0 = side_vert [Current ()->side][CURRENT_POINT(pt0)]; point1 = side_vert [Current ()->side][CURRENT_POINT(pt1)]; vector0 = Vertices (Segments (Current ()->segment)->verts [point0]); vector1 = Vertices (Segments (Current ()->segment)->verts [point1]); length = CalcLength(vector0,vector1); if (length >= F1_0) { delta.x = (FIX)(((double)(vector1->x - vector0->x) * (double)move_rate)/length); delta.y = (FIX)(((double)(vector1->y - vector0->y) * (double)move_rate)/length); delta.z = (FIX)(((double)(vector1->z - vector0->z) * (double)move_rate)/length); } else { delta.x = move_rate; delta.y = 0; delta.z = 0; } switch (m_selectMode){ case POINT_MODE: point = side_vert [Current ()->side][CURRENT_POINT(0)]; vect = Vertices (Segments (Current ()->segment)->verts [point]); vect->x += delta.x; vect->y += delta.y; vect->z += delta.z; theApp.SetModified (TRUE); break; case LINE_MODE: point = side_vert [Current ()->side][CURRENT_POINT(0)]; vect = Vertices (Segments (Current ()->segment)->verts [point]); vect->x += delta.x; vect->y += delta.y; vect->z += delta.z; point = side_vert [Current ()->side][CURRENT_POINT(1)]; vect = Vertices (Segments (Current ()->segment)->verts [point]); vect->x += delta.x; vect->y += delta.y; vect->z += delta.z; theApp.SetModified (TRUE); break; case SIDE_MODE: for (i = 0; i < 4; i++) { point = side_vert [Current ()->side][i]; vect = Vertices (Segments (Current ()->segment)->verts [point]); vect->x += delta.x; vect->y += delta.y; vect->z += delta.z; } theApp.SetModified (TRUE); break; case CUBE_MODE: for (i = 0; i < 8; i++) { vect = Vertices (Segments (Current ()->segment)->verts [i]); vect->x += delta.x; vect->y += delta.y; vect->z += delta.z; } theApp.SetModified (TRUE); break; case OBJECT_MODE: CurrObj ()->pos.x += delta.x; CurrObj ()->pos.y += delta.y; CurrObj ()->pos.z += delta.z; theApp.SetModified (TRUE); break; case BLOCK_MODE: bool bMoved = false; for (i = 0; i < MAX_VERTICES; i++) { if (*VertStatus (i) & MARKED_MASK) { Vertices (i)->x += delta.x; Vertices (i)->y += delta.y; Vertices (i)->z += delta.z; bMoved = true; } } theApp.SetModified (bMoved); break; } }
bool CMine::CalcSideLights (int segnum, int sidenum, vms_vector& source_center, vms_vector *source_corner, vms_vector& A, double *effect, double fLightScale, bool bIgnoreAngle) { CDSegment *seg = Segments (segnum); // calculate vector between center of source segment and center of child vms_vector B,center; CalcCenter (center,segnum,sidenum); B.x = center.x - source_center.x; B.y = center.y - source_center.y; B.z = center.z - source_center.z; // calculate angle between vectors (use dot product equation) if (!bIgnoreAngle) { double ratio,angle; double A_dot_B = (double)A.x * (double)B.x + (double)A.y * (double)B.y + (double)A.z * (double)B.z; double mag_A = my_sqrt( (double)A.x*(double)A.x +(double)A.y*(double)A.y +(double)A.z*(double)A.z); double mag_B = my_sqrt( (double)B.x*(double)B.x +(double)B.y*(double)B.y +(double)B.z*(double)B.z); if (mag_A == 0 || mag_B == 0) angle = (200.0 * M_PI)/180.0; // force a failure else { ratio = A_dot_B/(mag_A * mag_B); ratio = ((double)((int)(ratio*1000.0))) / 1000.0; if (ratio < -1.0 || ratio > (double)1.0) angle = (199.0 * M_PI)/180.0; // force a failure else angle = acos(ratio); } // if angle is less than 110 degrees // then we found a match if (angle >= (180.0 * M_PI)/180.0) return false; } int i, j; for (j = 0; j < 4; j++) { vms_vector corner; int vertnum = side_vert[sidenum][j]; int h = seg->verts[vertnum]; corner.x = Vertices (h)->x; corner.y = Vertices (h)->y; corner.z = Vertices (h)->z; double length = 20.0 * m_lightRenderDepth; for (i = 0; i < 4; i++) length = min (length, CalcLength (source_corner + i, &corner) / F1_0); length /= 10.0 * m_lightRenderDepth / 6.0; // divide by 1/2 a cubes length so opposite side // light is recuded by 1/4 effect [j] = 32; if (length > 1.0)//if (length < 20.0 * m_lightRenderDepth) // (roughly 4 standard cube lengths) effect [j] /= (length * length); effect [j] *= fLightScale; // else // effect [j] = 0; } // if any of the effects are > 0, then increment the // light for that side return (effect [0] != 0 || effect [1] != 0 || effect [2] != 0 || effect [3] != 0); }
// get our 'form' and lookup in the Operator Dictionary to fetch // our default data that may come from there. Then complete our setup // using attributes that we may have. To stay in sync, this function is // called very often. We depend on many things that may change around us. // However, we re-use unchanged values. void nsMathMLmoFrame::ProcessOperatorData() { // if we have been here before, we will just use our cached form nsOperatorFlags form = NS_MATHML_OPERATOR_GET_FORM(mFlags); nsAutoString value; // special bits are always kept in mFlags. // remember the mutable bit from ProcessTextData(). // Some chars are listed under different forms in the dictionary, // and there could be a form under which the char is mutable. // If the char is the core of an embellished container, we will keep // it mutable irrespective of the form of the embellished container. // Also remember the other special bits that we want to carry forward. mFlags &= NS_MATHML_OPERATOR_MUTABLE | NS_MATHML_OPERATOR_ACCENT | NS_MATHML_OPERATOR_MOVABLELIMITS | NS_MATHML_OPERATOR_CENTERED | NS_MATHML_OPERATOR_INVISIBLE; if (!mEmbellishData.coreFrame) { // i.e., we haven't been here before, the default form is infix form = NS_MATHML_OPERATOR_FORM_INFIX; // reset everything so that we don't keep outdated values around // in case of dynamic changes mEmbellishData.flags = 0; mEmbellishData.coreFrame = nullptr; mEmbellishData.leadingSpace = 0; mEmbellishData.trailingSpace = 0; if (mMathMLChar.Length() != 1) mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED; // else... retain the native direction obtained in ProcessTextData() if (!mFrames.FirstChild()) { return; } mEmbellishData.flags |= NS_MATHML_EMBELLISH_OPERATOR; mEmbellishData.coreFrame = this; // there are two particular things that we also need to record so that if our // parent is <mover>, <munder>, or <munderover>, they will treat us properly: // 1) do we have accent="true" // 2) do we have movablelimits="true" // they need the extra information to decide how to treat their scripts/limits // (note: <mover>, <munder>, or <munderover> need not necessarily be our // direct parent -- case of embellished operators) // default values from the Operator Dictionary were obtained in ProcessTextData() // and these special bits are always kept in mFlags if (NS_MATHML_OPERATOR_IS_ACCENT(mFlags)) mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENT; if (NS_MATHML_OPERATOR_IS_MOVABLELIMITS(mFlags)) mEmbellishData.flags |= NS_MATHML_EMBELLISH_MOVABLELIMITS; // see if the accent attribute is there GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::accent_, value); if (value.EqualsLiteral("true")) mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENT; else if (value.EqualsLiteral("false")) mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENT; // see if the movablelimits attribute is there GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::movablelimits_, value); if (value.EqualsLiteral("true")) mEmbellishData.flags |= NS_MATHML_EMBELLISH_MOVABLELIMITS; else if (value.EqualsLiteral("false")) mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_MOVABLELIMITS; // --------------------------------------------------------------------- // we will be called again to re-sync the rest of our state next time... // (nobody needs the other values below at this stage) mFlags |= form; return; } nsPresContext* presContext = PresContext(); // beware of bug 133814 - there is a two-way dependency in the // embellished hierarchy: our embellished ancestors need to set // their flags based on some of our state (set above), and here we // need to re-sync our 'form' depending on our outermost embellished // container. A null form here means that an earlier attempt to stretch // our mMathMLChar failed, in which case we don't bother re-stretching again if (form) { // get our outermost embellished container and its parent. // (we ensure that we are the core, not just a sibling of the core) nsIFrame* embellishAncestor = this; nsEmbellishData embellishData; nsIFrame* parentAncestor = this; do { embellishAncestor = parentAncestor; parentAncestor = embellishAncestor->GetParent(); GetEmbellishDataFrom(parentAncestor, embellishData); } while (embellishData.coreFrame == this); // flag if we have an embellished ancestor if (embellishAncestor != this) mFlags |= NS_MATHML_OPERATOR_EMBELLISH_ANCESTOR; else mFlags &= ~NS_MATHML_OPERATOR_EMBELLISH_ANCESTOR; // find the position of our outermost embellished container w.r.t // its siblings. nsIFrame* nextSibling = embellishAncestor->GetNextSibling(); nsIFrame* prevSibling = embellishAncestor->GetPrevSibling(); // flag to distinguish from a real infix if (!prevSibling && !nextSibling) mFlags |= NS_MATHML_OPERATOR_EMBELLISH_ISOLATED; else mFlags &= ~NS_MATHML_OPERATOR_EMBELLISH_ISOLATED; // find our form form = NS_MATHML_OPERATOR_FORM_INFIX; GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::form, value); if (!value.IsEmpty()) { if (value.EqualsLiteral("prefix")) form = NS_MATHML_OPERATOR_FORM_PREFIX; else if (value.EqualsLiteral("postfix")) form = NS_MATHML_OPERATOR_FORM_POSTFIX; } else { // set our form flag depending on the position if (!prevSibling && nextSibling) form = NS_MATHML_OPERATOR_FORM_PREFIX; else if (prevSibling && !nextSibling) form = NS_MATHML_OPERATOR_FORM_POSTFIX; } mFlags &= ~NS_MATHML_OPERATOR_FORM; // clear the old form bits mFlags |= form; // Use the default value suggested by the MathML REC. // http://www.w3.org/TR/MathML/chapter3.html#presm.mo.attrs // thickmathspace = 5/18em float lspace = 5.0f/18.0f; float rspace = 5.0f/18.0f; if (NS_MATHML_OPERATOR_IS_INVISIBLE(mFlags)) { // mMathMLChar has been reset in ProcessTextData so we can not find it // in the operator dictionary. The operator dictionary always uses // lspace = rspace = 0 for invisible operators. lspace = rspace = 0; } else { // lookup the operator dictionary nsAutoString data; mMathMLChar.GetData(data); nsMathMLOperators::LookupOperator(data, form, &mFlags, &lspace, &rspace); } if (lspace || rspace) { // Cache the default values of lspace and rspace. // since these values are relative to the 'em' unit, convert to twips now nscoord em; nsRefPtr<nsFontMetrics> fm; nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm)); GetEmHeight(fm, em); mEmbellishData.leadingSpace = NSToCoordRound(lspace * em); mEmbellishData.trailingSpace = NSToCoordRound(rspace * em); // tuning if we don't want too much extra space when we are a script. // (with its fonts, TeX sets lspace=0 & rspace=0 as soon as scriptlevel>0. // Our fonts can be anything, so...) if (StyleFont()->mScriptLevel > 0) { if (NS_MATHML_OPERATOR_EMBELLISH_IS_ISOLATED(mFlags)) { // could be an isolated accent or script, e.g., x^{+}, just zero out mEmbellishData.leadingSpace = 0; mEmbellishData.trailingSpace = 0; } else if (!NS_MATHML_OPERATOR_HAS_EMBELLISH_ANCESTOR(mFlags)) { mEmbellishData.leadingSpace /= 2; mEmbellishData.trailingSpace /= 2; } } } } // If we are an accent without explicit lspace="." or rspace=".", // we will ignore our default leading/trailing space // lspace // // "Specifies the leading space appearing before the operator" // // values: length // default: set by dictionary (thickmathspace) // // XXXfredw Support for negative and relative values is not implemented // (bug 805926). // Relative values will give a multiple of the current leading space, // which is not necessarily the default one. // nscoord leadingSpace = mEmbellishData.leadingSpace; GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::lspace_, value); if (!value.IsEmpty()) { nsCSSValue cssValue; if (nsMathMLElement::ParseNumericValue(value, cssValue, 0, mContent->OwnerDoc())) { if ((eCSSUnit_Number == cssValue.GetUnit()) && !cssValue.GetFloatValue()) leadingSpace = 0; else if (cssValue.IsLengthUnit()) leadingSpace = CalcLength(presContext, mStyleContext, cssValue); mFlags |= NS_MATHML_OPERATOR_LSPACE_ATTR; } } // rspace // // "Specifies the trailing space appearing after the operator" // // values: length // default: set by dictionary (thickmathspace) // // XXXfredw Support for negative and relative values is not implemented // (bug 805926). // Relative values will give a multiple of the current leading space, // which is not necessarily the default one. // nscoord trailingSpace = mEmbellishData.trailingSpace; GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::rspace_, value); if (!value.IsEmpty()) { nsCSSValue cssValue; if (nsMathMLElement::ParseNumericValue(value, cssValue, 0, mContent->OwnerDoc())) { if ((eCSSUnit_Number == cssValue.GetUnit()) && !cssValue.GetFloatValue()) trailingSpace = 0; else if (cssValue.IsLengthUnit()) trailingSpace = CalcLength(presContext, mStyleContext, cssValue); mFlags |= NS_MATHML_OPERATOR_RSPACE_ATTR; } } // little extra tuning to round lspace & rspace to at least a pixel so that // operators don't look as if they are colliding with their operands if (leadingSpace || trailingSpace) { nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1); if (leadingSpace && leadingSpace < onePixel) leadingSpace = onePixel; if (trailingSpace && trailingSpace < onePixel) trailingSpace = onePixel; } // the values that we get from our attributes override the dictionary mEmbellishData.leadingSpace = leadingSpace; mEmbellishData.trailingSpace = trailingSpace; // Now see if there are user-defined attributes that override the dictionary. // XXX If an attribute can be forced to be true when it is false in the // dictionary, then the following code has to change... // For each attribute overriden by the user, turn off its bit flag. // symmetric|movablelimits|separator|largeop|accent|fence|stretchy|form // special: accent and movablelimits are handled above, // don't process them here GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::stretchy_, value); if (value.EqualsLiteral("false")) { mFlags &= ~NS_MATHML_OPERATOR_STRETCHY; } else if (value.EqualsLiteral("true")) { mFlags |= NS_MATHML_OPERATOR_STRETCHY; } if (NS_MATHML_OPERATOR_IS_FENCE(mFlags)) { GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::fence_, value); if (value.EqualsLiteral("false")) mFlags &= ~NS_MATHML_OPERATOR_FENCE; } GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::largeop_, value); if (value.EqualsLiteral("false")) { mFlags &= ~NS_MATHML_OPERATOR_LARGEOP; } else if (value.EqualsLiteral("true")) { mFlags |= NS_MATHML_OPERATOR_LARGEOP; } if (NS_MATHML_OPERATOR_IS_SEPARATOR(mFlags)) { GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::separator_, value); if (value.EqualsLiteral("false")) mFlags &= ~NS_MATHML_OPERATOR_SEPARATOR; } GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::symmetric_, value); if (value.EqualsLiteral("false")) mFlags &= ~NS_MATHML_OPERATOR_SYMMETRIC; else if (value.EqualsLiteral("true")) mFlags |= NS_MATHML_OPERATOR_SYMMETRIC; // minsize // // "Specifies the minimum size of the operator when stretchy" // // values: length // default: set by dictionary (1em) // // We don't allow negative values. // Note: Contrary to other "length" values, unitless and percentage do not // give a multiple of the defaut value but a multiple of the operator at // normal size. // mMinSize = 0; GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::minsize_, value); if (!value.IsEmpty()) { nsCSSValue cssValue; if (nsMathMLElement::ParseNumericValue(value, cssValue, nsMathMLElement:: PARSE_ALLOW_UNITLESS, mContent->OwnerDoc())) { nsCSSUnit unit = cssValue.GetUnit(); if (eCSSUnit_Number == unit) mMinSize = cssValue.GetFloatValue(); else if (eCSSUnit_Percent == unit) mMinSize = cssValue.GetPercentValue(); else if (eCSSUnit_Null != unit) { mMinSize = float(CalcLength(presContext, mStyleContext, cssValue)); mFlags |= NS_MATHML_OPERATOR_MINSIZE_ABSOLUTE; } } } // maxsize // // "Specifies the maximum size of the operator when stretchy" // // values: length | "infinity" // default: set by dictionary (infinity) // // We don't allow negative values. // Note: Contrary to other "length" values, unitless and percentage do not // give a multiple of the defaut value but a multiple of the operator at // normal size. // mMaxSize = NS_MATHML_OPERATOR_SIZE_INFINITY; GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::maxsize_, value); if (!value.IsEmpty()) { nsCSSValue cssValue; if (nsMathMLElement::ParseNumericValue(value, cssValue, nsMathMLElement:: PARSE_ALLOW_UNITLESS, mContent->OwnerDoc())) { nsCSSUnit unit = cssValue.GetUnit(); if (eCSSUnit_Number == unit) mMaxSize = cssValue.GetFloatValue(); else if (eCSSUnit_Percent == unit) mMaxSize = cssValue.GetPercentValue(); else if (eCSSUnit_Null != unit) { mMaxSize = float(CalcLength(presContext, mStyleContext, cssValue)); mFlags |= NS_MATHML_OPERATOR_MAXSIZE_ABSOLUTE; } } } }
bool MmlParser::FeedChar(int ch) { bool continueFlag; if ('a' <= ch && ch <= 'z') ch = ch - 'a' + 'A'; do { continueFlag = false; if (_stat == STAT_Begin) { if (IsEOD(ch)) { // nothing to do } else if ('A' <= ch && ch <= 'G') { _operator = ch; _operatorSub = '\0'; _numAccum = 0; _cntDot = 0; _stat = STAT_Note; } else if (ch == 'R') { _operator = ch; _numAccum = 0; _cntDot = 0; _stat = STAT_RestLengthPre; } else if (ch == '&') { _operator = ch; } else if (ch == 'O') { _operator = ch; _numAccum = 0; _stat = STAT_OctavePre; } else if (ch == '>') { _operator = ch; if (_octave < 255) _octave++; } else if (ch == '<') { _operator = ch; if (_octave > 0) _octave--; } else if (ch == 'L') { _operator = ch; _numAccum = 0; _cntDot = 0; _stat = STAT_LengthPre; } else if (ch == 'V') { _operator = ch; _numAccum = 0; _stat = STAT_VolumePre; } else if (ch == '@') { _operator = ch; _numAccum = 0; _stat = STAT_TonePre; } else if (ch == 'T') { _operator = ch; _numAccum = 0; _stat = STAT_TempoPre; } else { // nothing to do } } else if (_stat == STAT_Note) { // -------- Note -------- if (ch == '#' || ch == '+' || ch == '-') { _operatorSub = ch; _stat = STAT_NoteLengthPre; } else if (IsDigit(ch)) { continueFlag = true; _stat = STAT_NoteLength; } else if (IsWhite(ch)) { // nothing to do } else { continueFlag = true; _stat = STAT_NoteFix; } } else if (_stat == STAT_NoteLengthPre) { if (IsDigit(ch)) { continueFlag = true; _stat = STAT_NoteLength; } else if (IsWhite(ch)) { // nothing to do } else { continueFlag = true; _stat = STAT_NoteFix; } } else if (_stat == STAT_NoteLength) { if (IsDigit(ch)) { _numAccum = _numAccum * 10 + (ch - '0'); } else if (ch == '.') { _cntDot++; } else { continueFlag = true; _stat = STAT_NoteFix; } } else if (_stat == STAT_NoteFix) { static const unsigned char noteTbl[] = { 9, 11, 0, 2, 4, 5, 7, }; unsigned char note = noteTbl[_operator - 'A'] + _octave * 12; if (_operatorSub == '#' || _operatorSub == '+') { if (note < 127) note++; } else if (_operatorSub == '-') { if (note > 0) note--; } else { // nothing to do } int length = CalcLength(_numAccum, _cntDot, _lengthDefault); _handler.MmlNote(*this, note, length); continueFlag = true; _stat = STAT_Begin; } else if (_stat == STAT_RestLengthPre) {// -------- Rest -------- if (IsDigit(ch)) { continueFlag = true; _stat = STAT_RestLength; } else if (IsWhite(ch)) { // nothing to do } else { continueFlag = true; _stat = STAT_RestFix; } } else if (_stat == STAT_RestLength) { if (IsDigit(ch)) { _numAccum = _numAccum * 10 + (ch - '0'); } else if (ch == '.') { _cntDot++; } else { continueFlag = true; _stat = STAT_RestFix; } } else if (_stat == STAT_RestFix) { int length = CalcLength(_numAccum, _cntDot, _lengthDefault); _handler.MmlRest(*this, length); continueFlag = true; _stat = STAT_Begin; } else if (_stat == STAT_OctavePre) { // -------- Octave -------- if (IsDigit(ch)) { continueFlag = true; _stat = STAT_Octave; } else if (IsWhite(ch)) { // nothing to do } else { continueFlag = true; _stat = STAT_OctaveFix; } } else if (_stat == STAT_Octave) { if (IsDigit(ch)) { _numAccum = _numAccum * 10 + (ch - '0'); } else { continueFlag = true; _stat = STAT_OctaveFix; } } else if (_stat == STAT_OctaveFix) { _octave = _numAccum; continueFlag = true; _stat = STAT_Begin; } else if (_stat == STAT_LengthPre) { // -------- Length -------- if (IsDigit(ch)) { continueFlag = true; _stat = STAT_Length; } else if (IsWhite(ch)) { // nothing to do } else { continueFlag = true; _stat = STAT_LengthFix; } } else if (_stat == STAT_Length) { if (IsDigit(ch)) { _numAccum = _numAccum * 10 + (ch - '0'); } else if (ch == '.') { _cntDot++; } else { continueFlag = true; _stat = STAT_LengthFix; } } else if (_stat == STAT_LengthFix) { _lengthDefault = CalcLength(_numAccum, _cntDot, _lengthDefault); continueFlag = true; _stat = STAT_Begin; } else if (_stat == STAT_VolumePre) { // -------- Volume -------- if (IsDigit(ch)) { continueFlag = true; _stat = STAT_Volume; } else if (IsWhite(ch)) { // nothing to do } else { continueFlag = true; _stat = STAT_VolumeFix; } } else if (_stat == STAT_Volume) { if (IsDigit(ch)) { _numAccum = _numAccum * 10 + (ch - '0'); } else { continueFlag = true; _stat = STAT_VolumeFix; } } else if (_stat == STAT_VolumeFix) { _volume = _numAccum; continueFlag = true; _stat = STAT_Begin; } else if (_stat == STAT_TonePre) { // ------- Tone -------- if (IsDigit(ch)) { continueFlag = true; _stat = STAT_Tone; } else if (IsWhite(ch)) { // nothing to do } else { continueFlag = true; _stat = STAT_ToneFix; } } else if (_stat == STAT_Tone) { if (IsDigit(ch)) { _numAccum = _numAccum * 10 + (ch - '0'); } else { continueFlag = true; _stat = STAT_ToneFix; } } else if (_stat == STAT_ToneFix) { _tone = _numAccum; continueFlag = true; _stat = STAT_Begin; } else if (_stat == STAT_TempoPre) { // -------- Tempo -------- if (IsDigit(ch)) { continueFlag = true; _stat = STAT_Tempo; } else if (IsWhite(ch)) { // nothing to do } else { continueFlag = true; _stat = STAT_TempoFix; } } else if (_stat == STAT_Tempo) { if (IsDigit(ch)) { _numAccum = _numAccum * 10 + (ch - '0'); } else { continueFlag = true; _stat = STAT_TempoFix; } } else if (_stat == STAT_TempoFix) { _tempo = _numAccum; continueFlag = true; _stat = STAT_Begin; } } while (continueFlag); return true; }