private ActiveNode TryBreakHere( IParagraphModel <TLine, TState> paragraph, IFrameModel frame, IBreakPoint breakPoint, ActiveNode prevNode, out bool doDeactivate) { var nextLineNumber = prevNode.LineNumber + 1; var suitableLength = frame.LengthOf(nextLineNumber); var constraint = new LineConstraint { SuitableLength = suitableLength }; var newStyle = new TState(); var line = paragraph.CreateLine(constraint, prevNode.Point, breakPoint, prevNode.Style, out newStyle); double ratio = _evaluator.ComputeAdjustmentRatio(line, suitableLength); doDeactivate = (ratio < -1 || _evaluator.IsForcedBreakPoint(breakPoint)); if (-1 <= ratio && ratio <= _tolerance) { var fitnessClass = _evaluator.ComputeFitnessClass(ratio); var prevIsFlagged = prevNode.Point.IsFlagged; var prevFitnessClass = prevNode.FitnessClass; var demerits = _evaluator.ComputeDemerits(breakPoint, ratio, fitnessClass, prevIsFlagged, prevFitnessClass); return(ActiveNode.CreateBreakNode(breakPoint, line, fitnessClass, newStyle, ratio, demerits, prevNode)); } else { return(null); } }
private List <ActiveNode> ComputeBreakPoints(IParagraphModel <TLine, TState> paragraph, IFrameModel frame) { var startNode = ActiveNode.CreateStartNode(paragraph.StartPoint); var storedActiveNodeList = new LinkedList <ActiveNode>(); storedActiveNodeList.AddLast(startNode); foreach (var breakPoint in paragraph.FeasibleBreakPoints) { var breakPointNodes = new HashSet <ActiveNode>(); var activeNodeNode = storedActiveNodeList.First; while (activeNodeNode != null) { ActiveNode activeNode = activeNodeNode.Value; bool doDeactivate; ActiveNode nextNode = TryBreakHere(paragraph, frame, breakPoint, activeNode, out doDeactivate); if (nextNode != null) { bool betterThanTheOthers = AddBetterActiveNode(breakPointNodes, nextNode); #if TRACE_TRY_BREAK Console.WriteLine("#ACTIVATE | {0}", nextNode); if (betterThanTheOthers) { Console.WriteLine("#...BETTER |"); } #endif } var next = activeNodeNode.Next; if (doDeactivate) { storedActiveNodeList.Remove(activeNodeNode); #if TRACE_TRY_BREAK if (nextNode != null) { Console.WriteLine("#ACCEPT From| {0:12} | To:{1:12}", activeNode, nextNode); } else { Console.WriteLine("#DECLINE From| {0:12}", activeNode); } #endif } activeNodeNode = next; } MergeActiveNodes(storedActiveNodeList, breakPointNodes); } var endedNodes = (from x in storedActiveNodeList where x.Point == paragraph.EndPoint select x); if (IsNotEmpty(endedNodes)) { var bestNode = FindTheWorstDemerits(endedNodes); storedActiveNodeList.Clear(); return(bestNode.TrackFromStartToHere()); } else { //失敗した場合は一行におさめる var line = ForceLayoutInOneLine(paragraph, frame); return(new List <ActiveNode> { ActiveNode.CreateBreakNode(paragraph.EndPoint, line, FitnessClass.Tight /*dummy*/, null, 0.0, 0.0, startNode) }); } }