)Ej.2dZddlmZddlmZddlZddlZdZefdZ e e fdZ dZ d Zd Zd Zd Zd ZdZdZdZdZdZdZdZddZGddeZddZdZedkr,ddlZddlZej ej!j"dSdS)zTRoutines for calculating bounding boxes, point in rectangle calculations and so on. )otRound)VectorNc|sdSd|D}d|D}t|t|t|t|fS)zCalculate the bounding rectangle of a 2D points array. Args: array: A sequence of 2D tuples. Returns: A four-item tuple representing the bounding rectangle ``(xMin, yMin, xMax, yMax)``. rrrrcg|]\}}|Sr.0xys KC:\PYTHON\MyICR_Suite\python\Lib\site-packages\fontTools/misc/arrayTools.py zcalcBounds..   1!   cg|]\}}|Srrr s r rzcalcBounds..rrminmax)arrayxsyss r calcBoundsr s^ z     B     B r77CGGSWWc"gg --rcTtfdt|DS)aCalculate the integer bounding rectangle of a 2D points array. Values are rounded to closest integer towards ``+Infinity`` using the :func:`fontTools.misc.fixedTools.otRound` function by default, unless an optional ``round`` function is passed. Args: array: A sequence of 2D tuples. round: A rounding function of type ``f(x: float) -> int``. Returns: A four-item tuple of integers representing the bounding rectangle: ``(xMin, yMin, xMax, yMax)``. c3.K|]}|VdS)Nr)r vrounds r z calcIntBounds..*s+55aq555555r)tupler)rrs `r calcIntBoundsrs0 5555:e#4#4555 5 55rc|\}}|||||fS|\}}}} ||||||||||| |fS)a_Add a point to a bounding rectangle. Args: bounds: A bounding rectangle expressed as a tuple ``(xMin, yMin, xMax, yMax), or None``. p: A 2D tuple representing a point. min,max: functions to compute the minimum and maximum. Returns: The updated bounding rectangle ``(xMin, yMin, xMax, yMax)``. r) boundsprrr r xMinyMinxMaxyMaxs r updateBoundsr'-seFQ ~!Qz#D$d 3tQ<<T1ss4||SSq\\ AArcZ|\}}|\}}}}||cxko|knco||cxko|kncS)a'Test if a point is inside a bounding rectangle. Args: p: A 2D tuple representing a point. rect: A bounding rectangle expressed as a tuple ``(xMin, yMin, xMax, yMax)``. Returns: ``True`` if the point is inside the rectangle, ``False`` otherwise. r)r"rectr r r#r$r%r&s r pointInRectr*@s^FQ!D$d A         6DA$5$5$5$5$5$5$5$56rcdt|dkrgS|\fd|DS)aDetermine which points are inside a bounding rectangle. Args: array: A sequence of 2D tuples. rect: A bounding rectangle expressed as a tuple ``(xMin, yMin, xMax, yMax)``. Returns: A list containing the points inside the rectangle. cVg|]%\}}|cxkoknco|cxkoknc&Srr)r r r r%r#r&r$s r rz pointsInRect..^sZ J J JDAqTQ    $     7TQ%6%6%6%6$%6%6%6%6 J J Jr)len)rr)r%r#r&r$s @@@@r pointsInRectr/PsM 5zzA~~ !D$d J J J J J J JE J J JJrcF|\}}tj|dz|dzzS)zCalculate the length of the given vector. Args: vector: A 2D tuple. Returns: The Euclidean length of the vector. )mathsqrt)vectorr r s r vectorLengthr5as) DAq 9QTAqD[ ! !!rcd|DS)zRound a list of floats to 16-bit signed integers. Args: array: List of float values. Returns: A list of rounded integers. cVg|]&}ttj|dz'S)g?)intr2floor)r is r rzasInt16..ws. 4 4 4C 1s7## $ $ 4 4 4rr)rs r asInt16r;ns 5 4e 4 4 44rc|\}}}}t||t||t||t||fS)aPNormalize a bounding box rectangle. This function "turns the rectangle the right way up", so that the following holds:: xMin <= xMax and yMin <= yMax Args: rect: A bounding rectangle expressed as a tuple ``(xMin, yMin, xMax, yMax)``. Returns: A normalized bounding rectangle. rr)r#r$r%r&s r normRectr>zsA $T4t tT??CdOOSt__c$oo MMrc4|\}}}}||z||z||z||zfS)a:Scale a bounding box rectangle. Args: rect: A bounding rectangle expressed as a tuple ``(xMin, yMin, xMax, yMax)``. x: Factor to scale the rectangle along the X axis. Y: Factor to scale the rectangle along the Y axis. Returns: A scaled bounding rectangle. r)r)r r r#r$r%r&s r scaleRectr@s1 $T4t !8TAXtax 11rc4|\}}}}||z||z||z||zfS)a@Offset a bounding box rectangle. Args: rect: A bounding rectangle expressed as a tuple ``(xMin, yMin, xMax, yMax)``. dx: Amount to offset the rectangle along the X axis. dY: Amount to offset the rectangle along the Y axis. Returns: An offset bounding rectangle. rr)dxdyr#r$r%r&s r offsetRectrE1 $T4t "9dRiD2I 55rc4|\}}}}||z||z||z ||z fS)aIInset a bounding box rectangle on all sides. Args: rect: A bounding rectangle expressed as a tuple ``(xMin, yMin, xMax, yMax)``. dx: Amount to inset the rectangle along the X axis. dY: Amount to inset the rectangle along the Y axis. Returns: An inset bounding rectangle. rrBs r insetRectrHrFrc|\}}}}|\}}}} t||t||t||t|| f\} } } } | | ks| | krdSd| | | | ffS)aTest for rectangle-rectangle intersection. Args: rect1: First bounding rectangle, expressed as tuples ``(xMin, yMin, xMax, yMax)``. rect2: Second bounding rectangle. Returns: A boolean and a rectangle. If the input rectangles intersect, returns ``True`` and the intersecting rectangle. Returns ``False`` and ``(0, 0, 0, 0)`` if the input rectangles don't intersect. )FrT)rrrect1rect2xMin1yMin1xMax1yMax1xMin2yMin2xMax2yMax2r#r$r%r&s r sectRectrUs$) UE5%#( UE5% E5 E5 E5 E5 D$d  t||tt||"" $dD) ))rc|\}}}}|\}}}} t||t||t||t|| f\} } } } | | | | fS)a0Determine union of bounding rectangles. Args: rect1: First bounding rectangle, expressed as tuples ``(xMin, yMin, xMax, yMax)``. rect2: Second bounding rectangle. Returns: The smallest rectangle in which both input rectangles are fully enclosed. rrJs r unionRectrWsu$) UE5%#( UE5% E5 E5 E5 E5 D$d $d ##rc0|\}}}}||zdz ||zdz fS)zDetermine rectangle center. Args: rect: Bounding rectangle, expressed as tuples ``(xMin, yMin, xMax, yMax)``. Returns: A 2D tuple representing the point at the center of the rectangle. r1rr=s r rectCenterrYs/ $T4t 4K1 td{a/ //rc&|\}}}}||z ||z zS)zDetermine rectangle area. Args: rect: Bounding rectangle, expressed as tuples ``(xMin, yMin, xMax, yMax)``. Returns: The area of the rectangle. rr=s r rectArear[s% $T4t 4KD4K ((rc$|\}}}}ttj|}ttj|}ttj|}ttj|}||||fS)aRound a rectangle to integer values. Guarantees that the resulting rectangle is NOT smaller than the original. Args: rect: Bounding rectangle, expressed as tuples ``(xMin, yMin, xMax, yMax)``. Returns: A rounded bounding rectangle. )r8r2r9ceilr=s r intRectr^ sy $T4t tz$ D tz$ D ty  D ty  D $d ##rr,c |dkrtd|t|\}}}}ttj||z |zttj||z |zttj||z |zttj||z |zfS)z >>> bounds = (72.3, -218.4, 1201.3, 919.1) >>> quantizeRect(bounds) (72, -219, 1202, 920) >>> quantizeRect(bounds, factor=10) (70, -220, 1210, 920) >>> quantizeRect(bounds, factor=100) (0, -300, 1300, 1000) r,z*Expected quantization factor >= 1, found: ) ValueErrorr>r8r2r9r])r)factorr#r$r%r&s r quantizeRectrbszzPfPPQQQ%d^^D$d DJtf} % % .// DJtf} % % .// DIdVm $ $v -.. DIdVm $ $v -..  rceZdZdZdS)rc:tjdtdS)NzffontTools.misc.arrayTools.Vector has been deprecated, please use fontTools.misc.vector.Vector instead.)warningswarnDeprecationWarning)selfargskwargss r __init__zVector.__init__5s(  4      rN)__name__ __module__ __qualname__rkrrr rr4s#     rrFc#K|sdS|rt|}nt|}t|d}|}|D] }||fV|} ||fVdS)aIterate over current and next items in iterable. Args: iterable: An iterable reverse: If true, iterate in reverse order. Returns: A iterable yielding two elements per iteration. Example: >>> tuple(pairwise([])) () >>> tuple(pairwise([], reverse=True)) () >>> tuple(pairwise([0])) ((0, 0),) >>> tuple(pairwise([0], reverse=True)) ((0, 0),) >>> tuple(pairwise([0, 1])) ((0, 1), (1, 0)) >>> tuple(pairwise([0, 1], reverse=True)) ((1, 0), (0, 1)) >>> tuple(pairwise([0, 1, 2])) ((0, 1), (1, 2), (2, 0)) >>> tuple(pairwise([0, 1, 2], reverse=True)) ((2, 1), (1, 0), (0, 2)) >>> tuple(pairwise(['a', 'b', 'c', 'd'])) (('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')) >>> tuple(pairwise(['a', 'b', 'c', 'd'], reverse=True)) (('d', 'c'), ('c', 'b'), ('b', 'a'), ('a', 'd')) N)reversediternext)iterablereverseitfirstabs r pairwisery=sB  h   (^^ TNNE A !f  e*rcdS)a >>> import math >>> calcBounds([]) (0, 0, 0, 0) >>> calcBounds([(0, 40), (0, 100), (50, 50), (80, 10)]) (0, 10, 80, 100) >>> updateBounds((0, 0, 0, 0), (100, 100)) (0, 0, 100, 100) >>> pointInRect((50, 50), (0, 0, 100, 100)) True >>> pointInRect((0, 0), (0, 0, 100, 100)) True >>> pointInRect((100, 100), (0, 0, 100, 100)) True >>> not pointInRect((101, 100), (0, 0, 100, 100)) True >>> list(pointsInRect([(50, 50), (0, 0), (100, 100), (101, 100)], (0, 0, 100, 100))) [True, True, True, False] >>> vectorLength((3, 4)) 5.0 >>> vectorLength((1, 1)) == math.sqrt(2) True >>> list(asInt16([0, 0.1, 0.5, 0.9])) [0, 0, 1, 1] >>> normRect((0, 10, 100, 200)) (0, 10, 100, 200) >>> normRect((100, 200, 0, 10)) (0, 10, 100, 200) >>> scaleRect((10, 20, 50, 150), 1.5, 2) (15.0, 40, 75.0, 300) >>> offsetRect((10, 20, 30, 40), 5, 6) (15, 26, 35, 46) >>> insetRect((10, 20, 50, 60), 5, 10) (15, 30, 45, 50) >>> insetRect((10, 20, 50, 60), -5, -10) (5, 10, 55, 70) >>> intersects, rect = sectRect((0, 10, 20, 30), (0, 40, 20, 50)) >>> not intersects True >>> intersects, rect = sectRect((0, 10, 20, 30), (5, 20, 35, 50)) >>> intersects 1 >>> rect (5, 20, 20, 30) >>> unionRect((0, 10, 20, 30), (0, 40, 20, 50)) (0, 10, 20, 50) >>> rectCenter((0, 0, 100, 200)) (50.0, 100.0) >>> rectCenter((0, 0, 100, 199.0)) (50.0, 99.5) >>> intRect((0.9, 2.9, 3.1, 4.1)) (0, 2, 4, 5) Nrrrr _testr{lsr__main__)r,)F)#__doc__fontTools.misc.roundToolsrfontTools.misc.vectorr_Vectorr2rerrrrr'r*r/r5r;r>r@rErHrUrWrYr[r^rbryr{rlsysdoctestexittestmodfailedrrr rs.-----333333  . . . '6666$!$BBBB& 7 7 7 KKK" " " " 5 5 5NNN& 2 2 2 6 6 6 6 6 6 ***6$$$. 0 0 0 ) ) )$$$(*     W   ,,,,^555p zJJJNNN CH_W_   %&&&&& r