diff options
author | Matthias Clasen <mclasen@redhat.com> | 2019-07-05 21:51:44 +0000 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2019-07-05 21:51:44 +0000 |
commit | afd269413f1982565b16645e6d7578d9c5a7fecf (patch) | |
tree | 2fe9341fd376503d383547b064208fd7f4939840 | |
parent | 05750deb6fbab92a1635b00085f819c96eafb38f (diff) | |
parent | ded8747655e4c83065753def16835c7a940ceaab (diff) | |
download | pango-afd269413f1982565b16645e6d7578d9c5a7fecf.tar.gz |
Merge branch 'line-height' into 'master'
Support line height
See merge request GNOME/pango!64
-rw-r--r-- | docs/layout.png | bin | 0 -> 27899 bytes | |||
-rw-r--r-- | docs/layout.svg | 497 | ||||
-rw-r--r-- | docs/meson.build | 2 | ||||
-rw-r--r-- | pango/fonts.c | 23 | ||||
-rw-r--r-- | pango/pango-font-private.h | 1 | ||||
-rw-r--r-- | pango/pango-font.h | 2 | ||||
-rw-r--r-- | pango/pango-layout-private.h | 1 | ||||
-rw-r--r-- | pango/pango-layout.c | 251 | ||||
-rw-r--r-- | pango/pango-layout.h | 9 | ||||
-rw-r--r-- | pango/pangocairo-coretextfont.c | 1 | ||||
-rw-r--r-- | pango/pangocairo-font.c | 38 | ||||
-rw-r--r-- | pango/pangofc-font.c | 59 | ||||
-rw-r--r-- | pango/pangowin32.c | 1 | ||||
-rw-r--r-- | utils/viewer-render.c | 6 |
14 files changed, 800 insertions, 91 deletions
diff --git a/docs/layout.png b/docs/layout.png Binary files differnew file mode 100644 index 00000000..bd28d5be --- /dev/null +++ b/docs/layout.png diff --git a/docs/layout.svg b/docs/layout.svg new file mode 100644 index 00000000..09f498b7 --- /dev/null +++ b/docs/layout.svg @@ -0,0 +1,497 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="210mm" + height="297mm" + viewBox="0 0 210 297" + version="1.1" + id="svg8" + sodipodi:docname="layout.svg" + inkscape:version="0.92.4 5da689c313, 2019-01-14"> + <defs + id="defs2"> + <marker + inkscape:stockid="TriangleInM" + orient="auto" + refY="0.0" + refX="0.0" + id="marker14051" + style="overflow:visible" + inkscape:isstock="true"> + <path + id="path14049" + d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + transform="scale(-0.4)" /> + </marker> + <marker + inkscape:isstock="true" + style="overflow:visible" + id="marker7942" + refX="0.0" + refY="0.0" + orient="auto" + inkscape:stockid="TriangleOutM"> + <path + transform="scale(0.4)" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " + id="path7940" /> + </marker> + <marker + inkscape:isstock="true" + style="overflow:visible" + id="marker7139" + refX="0.0" + refY="0.0" + orient="auto" + inkscape:stockid="TriangleOutM"> + <path + transform="scale(0.4)" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " + id="path7137" /> + </marker> + <marker + inkscape:isstock="true" + style="overflow:visible" + id="marker7071" + refX="0.0" + refY="0.0" + orient="auto" + inkscape:stockid="TriangleOutM"> + <path + transform="scale(0.4)" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " + id="path7069" /> + </marker> + <marker + inkscape:isstock="true" + style="overflow:visible" + id="marker6673" + refX="0.0" + refY="0.0" + orient="auto" + inkscape:stockid="TriangleInM" + inkscape:collect="always"> + <path + transform="scale(-0.4)" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " + id="path6671" /> + </marker> + <marker + inkscape:stockid="TriangleOutM" + orient="auto" + refY="0.0" + refX="0.0" + id="TriangleOutM" + style="overflow:visible" + inkscape:isstock="true" + inkscape:collect="always"> + <path + id="path1067" + d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + transform="scale(0.4)" /> + </marker> + <marker + inkscape:stockid="TriangleInM" + orient="auto" + refY="0.0" + refX="0.0" + id="TriangleInM" + style="overflow:visible" + inkscape:isstock="true" + inkscape:collect="always"> + <path + id="path1058" + d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + transform="scale(-0.4)" /> + </marker> + <marker + inkscape:stockid="Arrow1Sstart" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Sstart" + style="overflow:visible" + inkscape:isstock="true"> + <path + id="path934" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + transform="scale(0.2) translate(6,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Lend" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Lend" + style="overflow:visible;" + inkscape:isstock="true"> + <path + id="path925" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + transform="scale(0.8) rotate(180) translate(12.5,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Lstart" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Lstart" + style="overflow:visible" + inkscape:isstock="true"> + <path + id="path922" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1" + transform="scale(0.8) translate(12.5,0)" /> + </marker> + <marker + inkscape:stockid="TriangleInM" + orient="auto" + refY="0" + refX="0" + id="TriangleInM-0" + style="overflow:visible" + inkscape:isstock="true"> + <path + inkscape:connector-curvature="0" + id="path1058-6" + d="M 5.77,0 -2.88,5 V -5 Z" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" + transform="scale(-0.4)" /> + </marker> + <marker + inkscape:stockid="TriangleOutM" + orient="auto" + refY="0" + refX="0" + id="TriangleOutM-4" + style="overflow:visible" + inkscape:isstock="true"> + <path + inkscape:connector-curvature="0" + id="path1067-6" + d="M 5.77,0 -2.88,5 V -5 Z" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" + transform="scale(0.4)" /> + </marker> + <marker + inkscape:stockid="TriangleInM" + orient="auto" + refY="0" + refX="0" + id="TriangleInM-5" + style="overflow:visible" + inkscape:isstock="true"> + <path + inkscape:connector-curvature="0" + id="path1058-8" + d="M 5.77,0 -2.88,5 V -5 Z" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" + transform="scale(-0.4)" /> + </marker> + <marker + inkscape:stockid="TriangleOutM" + orient="auto" + refY="0" + refX="0" + id="TriangleOutM-6" + style="overflow:visible" + inkscape:isstock="true"> + <path + inkscape:connector-curvature="0" + id="path1067-2" + d="M 5.77,0 -2.88,5 V -5 Z" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" + transform="scale(0.4)" /> + </marker> + <marker + inkscape:isstock="true" + style="overflow:visible" + id="marker6673-6" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="TriangleInM"> + <path + inkscape:connector-curvature="0" + transform="scale(-0.4)" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" + d="M 5.77,0 -2.88,5 V -5 Z" + id="path6671-2" /> + </marker> + <marker + inkscape:isstock="true" + style="overflow:visible" + id="marker7139-9" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="TriangleOutM"> + <path + inkscape:connector-curvature="0" + transform="scale(0.4)" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" + d="M 5.77,0 -2.88,5 V -5 Z" + id="path7137-9" /> + </marker> + <marker + inkscape:stockid="TriangleInM" + orient="auto" + refY="0" + refX="0" + id="marker14051-8" + style="overflow:visible" + inkscape:isstock="true"> + <path + inkscape:connector-curvature="0" + id="path14049-1" + d="M 5.77,0 -2.88,5 V -5 Z" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" + transform="scale(-0.4)" /> + </marker> + <marker + inkscape:isstock="true" + style="overflow:visible" + id="marker7942-3" + refX="0" + refY="0" + orient="auto" + inkscape:stockid="TriangleOutM"> + <path + inkscape:connector-curvature="0" + transform="scale(0.4)" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1" + d="M 5.77,0 -2.88,5 V -5 Z" + id="path7940-1" /> + </marker> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="2.8284271" + inkscape:cx="62.552344" + inkscape:cy="945.78705" + inkscape:document-units="mm" + inkscape:current-layer="layer1" + showgrid="false" + showguides="true" + inkscape:snap-global="false" + inkscape:window-width="1920" + inkscape:window-height="1016" + inkscape:window-x="0" + inkscape:window-y="27" + inkscape:window-maximized="1" /> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <flowRoot + xml:space="preserve" + id="flowRoot815" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:85.33333588px;line-height:1.25;font-family:'DejaVu Serif';-inkscape-font-specification:'DejaVu Serif';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" + transform="scale(0.26458333)"><flowRegion + id="flowRegion817" + style="font-size:85.33333588px"><rect + id="rect819" + width="351.42859" + height="708.57141" + x="211.42857" + y="182.51968" + style="font-size:85.33333588px" /></flowRegion><flowPara + id="flowPara821" + style="font-size:96.00000121px">Mg</flowPara></flowRoot> <rect + style="fill:none;fill-opacity:1;stroke-width:0.26458333;stroke-miterlimit:4;stroke-dasharray:none;" + id="rect823" + width="47.624996" + height="24.209377" + x="52.255207" + y="52.260418" /> + <rect + style="fill:none;fill-opacity:1;stroke-width:0.26458333;stroke-miterlimit:4;stroke-dasharray:none" + id="rect845" + width="47.624996" + height="24.209377" + x="52.255207" + y="52.260418" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.13229167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 104.9316,52.260417 c -56.885887,0 -56.885887,0 -56.885887,0 v 0" + id="path849" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.13229167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 104.72835,71.043661 c -56.605254,0 -56.605254,0 -56.605254,0 v 0" + id="path849-8" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.13229167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 104.68306,76.469795 c -56.605249,0 -56.605249,0 -56.605249,0 v 0" + id="path849-8-0" + inkscape:connector-curvature="0" /> + <flowRoot + transform="matrix(0.26458333,0,0,0.26458333,-0.49993439,29.92432)" + xml:space="preserve" + id="flowRoot815-2" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:85.33333588px;line-height:1.25;font-family:'DejaVu Serif';-inkscape-font-specification:'DejaVu Serif';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"><flowRegion + id="flowRegion817-1" + style="font-size:85.33333588px"><rect + id="rect819-0" + width="351.42859" + height="708.57141" + x="211.42857" + y="182.51968" + style="font-size:85.33333588px" /></flowRegion><flowPara + id="flowPara821-5" + style="font-size:96px">Mg</flowPara></flowRoot> <rect + style="fill:none;fill-opacity:1;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none" + id="rect823-1" + width="47.624996" + height="24.209377" + x="51.75528" + y="82.184738" /> + <rect + style="fill:none;fill-opacity:1;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none" + id="rect845-1" + width="47.624996" + height="24.209377" + x="51.75528" + y="82.184738" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.13229167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 104.80585,82.184738 c -57.07298,0 -57.07298,0 -57.07298,0 v 0" + id="path849-0" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.13229167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 104.88322,100.82767 c -56.885878,0 -56.885878,0 -56.885878,0 v 0" + id="path849-8-8" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.13229167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 104.83794,106.39412 c -56.979428,0 -56.979428,0 -56.979428,0 v 0" + id="path849-8-0-5" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.25984162px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#TriangleInM);marker-end:url(#TriangleOutM)" + d="m 102.52459,70.326803 c -0.0936,-17.322528 -0.0936,-17.322528 -0.0936,-17.322528" + id="path920" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.26465496px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker6673);marker-end:url(#marker7139)" + d="m 102.45365,72.131518 c -0.13882,3.407593 -0.13882,3.407593 -0.13882,3.407593" + id="path10620" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:Cantarell;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + x="107.29259" + y="62.917221" + id="text13750"><tspan + sodipodi:role="line" + id="tspan13748" + x="107.29259" + y="62.917221" + style="stroke-width:0.26458332">Ascent</tspan><tspan + sodipodi:role="line" + x="107.29259" + y="68.208885" + style="stroke-width:0.26458332" + id="tspan13752" /></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:Cantarell;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + x="107.10825" + y="74.800102" + id="text13756"><tspan + sodipodi:role="line" + id="tspan13754" + x="107.10825" + y="74.800102" + style="stroke-width:0.26458332">Descent</tspan></text> + <path + style="fill:none;stroke:#000000;stroke-width:0.26465496px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker6673-6);marker-end:url(#marker7139-9)" + d="m 49.428752,77.64513 c -0.13882,3.407594 -0.13882,3.407594 -0.13882,3.407594" + id="path10620-0" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:Cantarell;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + x="28.730095" + y="80.757591" + id="text14031"><tspan + sodipodi:role="line" + id="tspan14029" + x="28.730095" + y="80.757591" + style="stroke-width:0.26458332">Spacing</tspan></text> + <path + style="fill:none;stroke:#000000;stroke-width:0.26399428px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker14051);marker-end:url(#marker7942)" + d="M 102.41047,105.39271 C 102.21678,77.415754 102.21678,77.415754 102.21678,77.415754" + id="path14041" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.26399428px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker14051-8);marker-end:url(#marker7942-3)" + d="M 53.385014,99.776343 C 53.19133,71.79943 53.19133,71.79943 53.19133,71.79943" + id="path14041-1" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:Cantarell;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332" + x="107.14215" + y="92.602859" + id="text16168"><tspan + sodipodi:role="line" + id="tspan16166" + x="107.14215" + y="92.602859" + style="stroke-width:0.26458332">Height</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333333px;line-height:1.25;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;" + x="12.434073" + y="62.795258" + id="text16172"><tspan + sodipodi:role="line" + id="tspan16188">Baseline-to-baseline</tspan><tspan + sodipodi:role="line" + id="tspan16190">distance</tspan></text> + <path + style="fill:none;stroke:#000000;stroke-width:0.12913886;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 53.1315,74.164103 c 0,0 -4.818074,0.125651 -7.969503,-0.151187 -2.845534,-0.249967 -5.290399,-0.985067 -7.513672,-1.679659 -4.72719,-1.476863 -7.250826,-3.884947 -7.250826,-3.884947" + id="path16192" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cssc" /> + </g> +</svg> diff --git a/docs/meson.build b/docs/meson.build index 9122dc3c..fbfb6072 100644 --- a/docs/meson.build +++ b/docs/meson.build @@ -58,7 +58,7 @@ content_files = [ ] html_images = [ - 'layout.gif', + 'layout.png', 'rotated-text.png', ] diff --git a/pango/fonts.c b/pango/fonts.c index 6a7778d3..f273cd26 100644 --- a/pango/fonts.c +++ b/pango/fonts.c @@ -1793,6 +1793,7 @@ pango_font_get_metrics (PangoFont *font, metrics->ascent = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_HEIGHT; metrics->descent = 0; + metrics->height = 0; metrics->approximate_char_width = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_WIDTH; metrics->approximate_digit_width = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_WIDTH; metrics->underline_position = -PANGO_SCALE; @@ -1940,6 +1941,28 @@ pango_font_metrics_get_descent (PangoFontMetrics *metrics) } /** + * pango_font_metrics_get_height: + * @metrics: a #PangoFontMetrics structure + * + * Gets the line height from a font metrics structure. The + * line height is the distance between successive baselines + * in wrapped text. + * + * If the line height is not available, 0 is returned. + * + * Return value: the height, in Pango units + * + * Since: 1.44 + */ +int +pango_font_metrics_get_height (PangoFontMetrics *metrics) +{ + g_return_val_if_fail (metrics != NULL, 0); + + return metrics->height; +} + +/** * pango_font_metrics_get_approximate_char_width: * @metrics: a #PangoFontMetrics structure * diff --git a/pango/pango-font-private.h b/pango/pango-font-private.h index 13b05254..44d19dee 100644 --- a/pango/pango-font-private.h +++ b/pango/pango-font-private.h @@ -41,6 +41,7 @@ struct _PangoFontMetrics int ascent; int descent; + int height; int approximate_char_width; int approximate_digit_width; int underline_position; diff --git a/pango/pango-font.h b/pango/pango-font.h index 60501216..ceaf9643 100644 --- a/pango/pango-font.h +++ b/pango/pango-font.h @@ -335,6 +335,8 @@ PANGO_AVAILABLE_IN_ALL int pango_font_metrics_get_ascent (PangoFontMetrics *metrics) G_GNUC_PURE; PANGO_AVAILABLE_IN_ALL int pango_font_metrics_get_descent (PangoFontMetrics *metrics) G_GNUC_PURE; +PANGO_AVAILABLE_IN_1_44 +int pango_font_metrics_get_height (PangoFontMetrics *metrics) G_GNUC_PURE; PANGO_AVAILABLE_IN_ALL int pango_font_metrics_get_approximate_char_width (PangoFontMetrics *metrics) G_GNUC_PURE; PANGO_AVAILABLE_IN_ALL diff --git a/pango/pango-layout-private.h b/pango/pango-layout-private.h index 4b5327ee..38e2e196 100644 --- a/pango/pango-layout-private.h +++ b/pango/pango-layout-private.h @@ -55,6 +55,7 @@ struct _PangoLayout int height; /* ellipsize width, in device units if positive, number of lines if negative */ int indent; /* amount by which first line should be shorter */ int spacing; /* spacing between lines */ + float line_spacing; /* factor to apply to line height */ guint justify : 1; guint alignment : 2; diff --git a/pango/pango-layout.c b/pango/pango-layout.c index a3850843..1ba614e1 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -49,8 +49,8 @@ * treat the results of a #PangoLayout as a list of lines. * * <figure id="parameters"> - * <title>Adjustable parameters for a PangoLayout</title> - * <graphic fileref="layout.gif" format="GIF"></graphic> + * <title>Adjustable parameters (on the left) and font metrics (on the right) for a PangoLayout</title> + * <graphic fileref="layout.png" format="PNG"></graphic> * </figure> * * The #PangoLayout structure is opaque, and has no user-visible @@ -113,6 +113,7 @@ struct _PangoLayoutLinePrivate } cache_status; PangoRectangle ink_rect; PangoRectangle logical_rect; + int height; }; struct _PangoLayoutClass @@ -189,6 +190,7 @@ pango_layout_init (PangoLayout *layout) layout->height = -1; layout->indent = 0; layout->spacing = 0; + layout->line_spacing = 1.0; layout->alignment = PANGO_ALIGN_LEFT; layout->justify = FALSE; @@ -555,8 +557,17 @@ pango_layout_get_indent (PangoLayout *layout) * @layout: a #PangoLayout. * @spacing: the amount of spacing * - * Sets the amount of spacing in Pango unit between the lines of the - * layout. + * Sets the amount of spacing in Pango unit between + * the lines of the layout. When placing lines with + * spacing, Pango arranges things so that + * + * line2.top = line1.bottom + spacing + * + * Note: Since 1.44, Pango defaults to using the + * line height (as determined by the font) for placing + * lines. The @spacing set with this function is only + * taken into account when the line-height factor is + * set to zero with pango_layout_set_line_spacing(). **/ void pango_layout_set_spacing (PangoLayout *layout, @@ -587,6 +598,59 @@ pango_layout_get_spacing (PangoLayout *layout) } /** + * pango_layout_set_line_spacing: + * @layout: a #PangoLayout + * @factor: the new line spacing factor + * + * Sets a factor for line spacing. + * Typical values are: 0, 1, 1.5, 2. + * The default values is 1. + * + * If @factor is non-zero, lines are placed + * so that + * + * baseline2 = baseline1 + factor * height2 + * + * where height2 is the line height of the + * second line (as determined by the font(s)). + * In this case, the spacing set with + * pango_layout_set_spacing() is ignored. + * + * If @factor is zero, spacing is applied as + * before. + * + * Since: 1.44 + */ +void +pango_layout_set_line_spacing (PangoLayout *layout, + float factor) +{ + g_return_if_fail (layout != NULL); + + if (layout->line_spacing != factor) + { + layout->line_spacing = factor; + layout_changed (layout); + } +} + +/** + * pango_layout_get_line_spacing: + * @layout: a #PangoLayout + * + * Gets the value that has been + * set with pango_layout_set_line_spacing(). + * + * Since: 1.44 + */ +float +pango_layout_get_line_spacing (PangoLayout *layout) +{ + g_return_val_if_fail (layout != NULL, 1.0); + return layout->line_spacing; +} + +/** * pango_layout_set_attributes: * @layout: a #PangoLayout * @attrs: (allow-none) (transfer none): a #PangoAttrList, can be %NULL @@ -2481,6 +2545,11 @@ get_x_offset (PangoLayout *layout, } static void +pango_layout_line_get_extents_and_height (PangoLayoutLine *line, + PangoRectangle *ink, + PangoRectangle *logical, + int *height); +static void get_line_extents_layout_coords (PangoLayout *layout, PangoLayoutLine *line, int layout_width, @@ -2493,29 +2562,43 @@ get_line_extents_layout_coords (PangoLayout *layout, /* Line extents in line coords (origin at line baseline) */ PangoRectangle line_ink; PangoRectangle line_logical; + gboolean first_line; + int new_baseline; + int height; + + if (layout->lines->data == line) + first_line = TRUE; + else + first_line = FALSE; - pango_layout_line_get_extents (line, line_ink_layout ? &line_ink : NULL, - &line_logical); + pango_layout_line_get_extents_and_height (line, line_ink_layout ? &line_ink : NULL, + &line_logical, + &height); get_x_offset (layout, line, layout_width, line_logical.width, &x_offset); + if (first_line || !baseline || layout->line_spacing == 0.0) + new_baseline = y_offset - line_logical.y; + else + new_baseline = *baseline + layout->line_spacing * height; + /* Convert the line's extents into layout coordinates */ if (line_ink_layout) { *line_ink_layout = line_ink; line_ink_layout->x = line_ink.x + x_offset; - line_ink_layout->y = y_offset - line_logical.y + line_ink.y; + line_ink_layout->y = new_baseline + line_ink.y; } if (line_logical_layout) { *line_logical_layout = line_logical; line_logical_layout->x = line_logical.x + x_offset; - line_logical_layout->y = y_offset; + line_logical_layout->y = new_baseline + line_logical.y; } if (baseline) - *baseline = y_offset - line_logical.y; + *baseline = new_baseline; } /* if non-NULL line_extents returns a list of line extents @@ -2532,6 +2615,7 @@ pango_layout_get_extents_internal (PangoLayout *layout, int width; gboolean need_width = FALSE; int line_index = 0; + int baseline; g_return_if_fail (layout != NULL); @@ -2598,6 +2682,7 @@ pango_layout_get_extents_internal (PangoLayout *layout, *line_extents = g_malloc (sizeof (Extents) * layout->line_count); } + baseline = 0; line_list = layout->lines; while (line_list) { @@ -2610,8 +2695,6 @@ pango_layout_get_extents_internal (PangoLayout *layout, /* This block gets the line extents in layout coords */ { - int baseline; - get_line_extents_layout_coords (layout, line, width, y_offset, &baseline, @@ -2683,14 +2766,10 @@ pango_layout_get_extents_internal (PangoLayout *layout, } } - logical_rect->height += line_logical_layout.height; - - /* No space after the last line, of course. */ - if (line_list->next != NULL) - logical_rect->height += layout->spacing; + logical_rect->height = line_logical_layout.y + line_logical_layout.height - logical_rect->y; } - y_offset += line_logical_layout.height + layout->spacing; + y_offset = line_logical_layout.y + line_logical_layout.height + layout->spacing; line_list = line_list->next; line_index ++; } @@ -4544,12 +4623,14 @@ pango_layout_line_get_empty_extents (PangoLayoutLine *line, } static void -pango_layout_run_get_extents (PangoLayoutRun *run, - PangoRectangle *run_ink, - PangoRectangle *run_logical) +pango_layout_run_get_extents_and_height (PangoLayoutRun *run, + PangoRectangle *run_ink, + PangoRectangle *run_logical, + int *height) { PangoRectangle logical; ItemProperties properties; + PangoFontMetrics *metrics = NULL; if (G_UNLIKELY (!run_ink && !run_logical)) return; @@ -4573,15 +4654,21 @@ pango_layout_run_get_extents (PangoLayoutRun *run, if (run_ink && (properties.uline != PANGO_UNDERLINE_NONE || properties.strikethrough)) { - PangoFontMetrics *metrics = pango_font_get_metrics (run->item->analysis.font, - run->item->analysis.language); - int underline_thickness = pango_font_metrics_get_underline_thickness (metrics); - int underline_position = pango_font_metrics_get_underline_position (metrics); - int strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness (metrics); - int strikethrough_position = pango_font_metrics_get_strikethrough_position (metrics); - + int underline_thickness; + int underline_position; + int strikethrough_thickness; + int strikethrough_position; int new_pos; + if (!metrics) + metrics = pango_font_get_metrics (run->item->analysis.font, + run->item->analysis.language); + + underline_thickness = pango_font_metrics_get_underline_thickness (metrics); + underline_position = pango_font_metrics_get_underline_position (metrics); + strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness (metrics); + strikethrough_position = pango_font_metrics_get_strikethrough_position (metrics); + /* the underline/strikethrough takes x,width of logical_rect. reflect * that into ink_rect. */ @@ -4625,8 +4712,14 @@ pango_layout_run_get_extents (PangoLayoutRun *run, g_critical ("unknown underline mode"); break; } + } - pango_font_metrics_unref (metrics); + if (height) + { + if (!metrics) + metrics = pango_font_get_metrics (run->item->analysis.font, + run->item->analysis.language); + *height = pango_font_metrics_get_height (metrics); } if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE) @@ -4648,24 +4741,16 @@ pango_layout_run_get_extents (PangoLayoutRun *run, if (run_logical) run_logical->y -= properties.rise; } + + if (metrics) + pango_font_metrics_unref (metrics); } -/** - * pango_layout_line_get_extents: - * @line: a #PangoLayoutLine - * @ink_rect: (out) (allow-none): rectangle used to store the extents of - * the glyph string as drawn, or %NULL - * @logical_rect: (out) (allow-none):rectangle used to store the logical - * extents of the glyph string, or %NULL - * - * Computes the logical and ink extents of a layout line. See - * pango_font_get_glyph_extents() for details about the interpretation - * of the rectangles. - */ -void -pango_layout_line_get_extents (PangoLayoutLine *line, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect) +static void +pango_layout_line_get_extents_and_height (PangoLayoutLine *line, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect, + int *height) { PangoLayoutLinePrivate *private = (PangoLayoutLinePrivate *)line; GSList *tmp_list; @@ -4685,6 +4770,8 @@ pango_layout_line_get_extents (PangoLayoutLine *line, *ink_rect = private->ink_rect; if (logical_rect) *logical_rect = private->logical_rect; + if (height) + *height = private->height; return; } case NOT_CACHED: @@ -4694,6 +4781,8 @@ pango_layout_line_get_extents (PangoLayoutLine *line, ink_rect = &private->ink_rect; if (!logical_rect) logical_rect = &private->logical_rect; + if (!height) + height = &private->height; break; } case LEAKED: @@ -4718,6 +4807,9 @@ pango_layout_line_get_extents (PangoLayoutLine *line, logical_rect->height = 0; } + if (height) + *height = 0; + tmp_list = line->runs; while (tmp_list) { @@ -4725,10 +4817,12 @@ pango_layout_line_get_extents (PangoLayoutLine *line, int new_pos; PangoRectangle run_ink; PangoRectangle run_logical; + int run_height; - pango_layout_run_get_extents (run, - ink_rect ? &run_ink : NULL, - &run_logical); + pango_layout_run_get_extents_and_height (run, + ink_rect ? &run_ink : NULL, + &run_logical, + height ? &run_height : NULL); if (ink_rect) { @@ -4752,9 +4846,9 @@ pango_layout_line_get_extents (PangoLayoutLine *line, } if (logical_rect) - { - new_pos = MIN (logical_rect->x, x_pos + run_logical.x); - logical_rect->width = MAX (logical_rect->x + logical_rect->width, + { + new_pos = MIN (logical_rect->x, x_pos + run_logical.x); + logical_rect->width = MAX (logical_rect->x + logical_rect->width, x_pos + run_logical.x + run_logical.width) - new_pos; logical_rect->x = new_pos; @@ -4762,10 +4856,13 @@ pango_layout_line_get_extents (PangoLayoutLine *line, logical_rect->height = MAX (logical_rect->y + logical_rect->height, run_logical.y + run_logical.height) - new_pos; logical_rect->y = new_pos; - } + } + + if (height) + *height = MAX (*height, run_height); - x_pos += run_logical.width; - tmp_list = tmp_list->next; + x_pos += run_logical.width; + tmp_list = tmp_list->next; } if (logical_rect && !line->runs) @@ -4777,10 +4874,49 @@ pango_layout_line_get_extents (PangoLayoutLine *line, private->ink_rect = *ink_rect; if (&private->logical_rect != logical_rect) private->logical_rect = *logical_rect; + if (&private->height != height) + private->height = *height; private->cache_status = CACHED; } } +/** + * pango_layout_line_get_extents: + * @line: a #PangoLayoutLine + * @ink_rect: (out) (allow-none): rectangle used to store the extents of + * the glyph string as drawn, or %NULL + * @logical_rect: (out) (allow-none):rectangle used to store the logical + * extents of the glyph string, or %NULL + * + * Computes the logical and ink extents of a layout line. See + * pango_font_get_glyph_extents() for details about the interpretation + * of the rectangles. + */ +void +pango_layout_line_get_extents (PangoLayoutLine *line, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + pango_layout_line_get_extents_and_height (line, ink_rect, logical_rect, NULL); +} + +/** + * pango_layout_line_get_height: + * @line: a #PangoLayoutLine + * @height: (out) (allow-none): return location for the line height + * + * Computes the height of the line, ie the distance between + * this and the previous lines baseline. + * + * Since: 1.44 + */ +void +pango_layout_line_get_height (PangoLayoutLine *line, + int *height) +{ + pango_layout_line_get_extents_and_height (line, NULL, NULL, height); +} + static PangoLayoutLine * pango_layout_line_new (PangoLayout *layout) { @@ -6307,7 +6443,7 @@ pango_layout_iter_get_run_extents (PangoLayoutIter *iter, if (iter->run) { - pango_layout_run_get_extents (iter->run, ink_rect, logical_rect); + pango_layout_run_get_extents_and_height (iter->run, ink_rect, logical_rect, NULL); if (ink_rect) { @@ -6372,7 +6508,7 @@ pango_layout_iter_get_line_extents (PangoLayoutIter *iter, get_line_extents_layout_coords (iter->layout, iter->line, iter->layout_width, ext->logical_rect.y, - NULL, + NULL, ink_rect, NULL); } @@ -6395,7 +6531,10 @@ pango_layout_iter_get_line_extents (PangoLayoutIter *iter, * The Y positions are in layout coordinates (origin at top left of the * entire layout). * - **/ + * Note: Since 1.44, Pango uses line heights for placing lines, + * and there may be gaps between the ranges returned by this + * function. + */ void pango_layout_iter_get_line_yrange (PangoLayoutIter *iter, int *y0, diff --git a/pango/pango-layout.h b/pango/pango-layout.h index b095a303..96155715 100644 --- a/pango/pango-layout.h +++ b/pango/pango-layout.h @@ -206,6 +206,11 @@ void pango_layout_set_spacing (PangoLayout *la int spacing); PANGO_AVAILABLE_IN_ALL int pango_layout_get_spacing (PangoLayout *layout); +PANGO_AVAILABLE_IN_1_44 +void pango_layout_set_line_spacing (PangoLayout *layout, + float spread); +PANGO_AVAILABLE_IN_1_44 +float pango_layout_get_line_spacing (PangoLayout *layout); PANGO_AVAILABLE_IN_ALL void pango_layout_set_justify (PangoLayout *layout, gboolean justify); @@ -352,6 +357,10 @@ PANGO_AVAILABLE_IN_ALL void pango_layout_line_get_extents (PangoLayoutLine *line, PangoRectangle *ink_rect, PangoRectangle *logical_rect); +PANGO_AVAILABLE_IN_1_44 +void pango_layout_line_get_height (PangoLayoutLine *line, + int *height); + PANGO_AVAILABLE_IN_ALL void pango_layout_line_get_pixel_extents (PangoLayoutLine *layout_line, PangoRectangle *ink_rect, diff --git a/pango/pangocairo-coretextfont.c b/pango/pangocairo-coretextfont.c index 9dc33447..162d08c3 100644 --- a/pango/pangocairo-coretextfont.c +++ b/pango/pangocairo-coretextfont.c @@ -139,6 +139,7 @@ pango_cairo_core_text_font_create_base_metrics_for_context (PangoCairoFont *font metrics->ascent = CTFontGetAscent (ctfont) * PANGO_SCALE; metrics->descent = CTFontGetDescent (ctfont) * PANGO_SCALE; + metrics->height = (CTFontGetAscent (ctfont) + CTFontGetDescent (ctfont) + CTFontGetLeading (ctfont) * PANGO_SCALE; metrics->underline_position = CTFontGetUnderlinePosition (ctfont) * PANGO_SCALE; metrics->underline_thickness = CTFontGetUnderlineThickness (ctfont) * PANGO_SCALE; diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c index cc2e7bee..7915be6f 100644 --- a/pango/pangocairo-font.c +++ b/pango/pangocairo-font.c @@ -224,6 +224,7 @@ _pango_cairo_font_get_metrics (PangoFont *font, PangoCairoFontPrivate *cf_priv = PANGO_CAIRO_FONT_PRIVATE (font); PangoCairoFontMetricsInfo *info = NULL; /* Quiet gcc */ GSList *tmp_list; + static int in_get_metrics; const char *sample_str = pango_language_get_sample_string (language); @@ -293,35 +294,43 @@ _pango_cairo_font_get_metrics (PangoFont *font, info->metrics->ascent *= xscale; info->metrics->descent *= xscale; + info->metrics->height *= xscale; info->metrics->underline_position *= xscale; info->metrics->underline_thickness *= xscale; info->metrics->strikethrough_position *= xscale; info->metrics->strikethrough_thickness *= xscale; } - /* Set the matrix on the context so we don't have to adjust the derived * metrics. */ pango_context_set_matrix (context, &pango_matrix); - /* Update approximate_*_width now */ - layout = pango_layout_new (context); - desc = pango_font_describe_with_absolute_size (font); - pango_layout_set_font_description (layout, desc); - pango_font_description_free (desc); + /* Ugly. We need to prevent recursion when we call into + * PangoLayout to determine approximate char width. + */ + if (!in_get_metrics) + { + in_get_metrics = 1; - pango_layout_set_text (layout, sample_str, -1); - pango_layout_get_extents (layout, NULL, &extents); + /* Update approximate_*_width now */ + layout = pango_layout_new (context); + desc = pango_font_describe_with_absolute_size (font); + pango_layout_set_font_description (layout, desc); + pango_font_description_free (desc); - sample_str_width = pango_utf8_strwidth (sample_str); - g_assert (sample_str_width > 0); - info->metrics->approximate_char_width = extents.width / sample_str_width; + pango_layout_set_text (layout, sample_str, -1); + pango_layout_get_extents (layout, NULL, &extents); - pango_layout_set_text (layout, "0123456789", -1); - info->metrics->approximate_digit_width = max_glyph_width (layout); + sample_str_width = pango_utf8_strwidth (sample_str); + g_assert (sample_str_width > 0); + info->metrics->approximate_char_width = extents.width / sample_str_width; - g_object_unref (layout); + pango_layout_set_text (layout, "0123456789", -1); + info->metrics->approximate_digit_width = max_glyph_width (layout); + g_object_unref (layout); + in_get_metrics = 0; + } /* We may actually reuse ascent/descent we got from cairo here. that's * in cf_priv->font_extents. @@ -355,6 +364,7 @@ _pango_cairo_font_get_metrics (PangoFont *font, g_object_unref (fontmap); } +out: return pango_font_metrics_ref (info->metrics); } diff --git a/pango/pangofc-font.c b/pango/pangofc-font.c index 7fd7db0f..79fb07c1 100644 --- a/pango/pangofc-font.c +++ b/pango/pangofc-font.c @@ -390,6 +390,7 @@ get_face_metrics (PangoFcFont *fcfont, { metrics->descent = 0; metrics->ascent = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_HEIGHT; + metrics->height = metrics->ascent; metrics->underline_thickness = PANGO_SCALE; metrics->underline_position = - PANGO_SCALE; metrics->strikethrough_thickness = PANGO_SCALE; @@ -422,24 +423,32 @@ get_face_metrics (PangoFcFont *fcfont, vector.y = face->size->metrics.ascender; FT_Vector_Transform (&vector, &ft_matrix); metrics->ascent = PANGO_UNITS_26_6 (vector.y); + + vector.x = 0; + vector.y = face->size->metrics.height; + FT_Vector_Transform (&vector, &ft_matrix); + metrics->height = PANGO_UNITS_26_6 (vector.y); } else if (fcfont->is_hinted || (face->face_flags & FT_FACE_FLAG_SCALABLE) == 0) { metrics->descent = - PANGO_UNITS_26_6 (face->size->metrics.descender); metrics->ascent = PANGO_UNITS_26_6 (face->size->metrics.ascender); + metrics->height = PANGO_UNITS_26_6 (face->size->metrics.height); } else { - FT_Fixed ascender, descender; + FT_Fixed ascender, descender, height; descender = FT_MulFix (face->descender, face->size->metrics.y_scale); metrics->descent = - PANGO_UNITS_26_6 (descender); ascender = FT_MulFix (face->ascender, face->size->metrics.y_scale); metrics->ascent = PANGO_UNITS_26_6 (ascender); - } + height = FT_MulFix (face->height, face->size->metrics.y_scale); + metrics->height = PANGO_UNITS_26_6 (height); + } metrics->underline_thickness = 0; metrics->underline_position = 0; @@ -545,6 +554,7 @@ pango_fc_font_get_metrics (PangoFont *font, PangoFcFont *fcfont = PANGO_FC_FONT (font); PangoFcMetricsInfo *info = NULL; /* Quiet gcc */ GSList *tmp_list; + static int in_get_metrics; const char *sample_str = pango_language_get_sample_string (language); @@ -570,6 +580,9 @@ pango_fc_font_get_metrics (PangoFont *font, info = g_slice_new0 (PangoFcMetricsInfo); + /* Note: we need to add info to the list before calling + * into PangoLayout below, to prevent recursion + */ fcfont->metrics_by_lang = g_slist_prepend (fcfont->metrics_by_lang, info); @@ -580,29 +593,35 @@ pango_fc_font_get_metrics (PangoFont *font, info->metrics = pango_fc_font_create_base_metrics_for_context (fcfont, context); - { /* Compute derived metrics */ - PangoLayout *layout; - PangoRectangle extents; - const char *sample_str = pango_language_get_sample_string (language); - PangoFontDescription *desc = pango_font_describe_with_absolute_size (font); - gulong sample_str_width; + if (!in_get_metrics) + { + in_get_metrics = 1; - layout = pango_layout_new (context); - pango_layout_set_font_description (layout, desc); - pango_font_description_free (desc); + /* Compute derived metrics */ + PangoLayout *layout; + PangoRectangle extents; + const char *sample_str = pango_language_get_sample_string (language); + PangoFontDescription *desc = pango_font_describe_with_absolute_size (font); + gulong sample_str_width; - pango_layout_set_text (layout, sample_str, -1); - pango_layout_get_extents (layout, NULL, &extents); + layout = pango_layout_new (context); + pango_layout_set_font_description (layout, desc); + pango_font_description_free (desc); - sample_str_width = pango_utf8_strwidth (sample_str); - g_assert (sample_str_width > 0); - info->metrics->approximate_char_width = extents.width / sample_str_width; + pango_layout_set_text (layout, sample_str, -1); + pango_layout_get_extents (layout, NULL, &extents); - pango_layout_set_text (layout, "0123456789", -1); - info->metrics->approximate_digit_width = max_glyph_width (layout); + sample_str_width = pango_utf8_strwidth (sample_str); + g_assert (sample_str_width > 0); + info->metrics->approximate_char_width = extents.width / sample_str_width; - g_object_unref (layout); - } + pango_layout_set_text (layout, "0123456789", -1); + info->metrics->approximate_digit_width = max_glyph_width (layout); + + g_object_unref (layout); + + in_get_metrics = 0; + } g_object_unref (context); g_object_unref (fontmap); diff --git a/pango/pangowin32.c b/pango/pangowin32.c index 630898e0..6f60a70c 100644 --- a/pango/pangowin32.c +++ b/pango/pangowin32.c @@ -575,6 +575,7 @@ pango_win32_font_get_metrics (PangoFont *font, metrics->ascent = tm.tmAscent * PANGO_SCALE; metrics->descent = tm.tmDescent * PANGO_SCALE; + metrics->height = (tm.tmHeight + tm.tmInternalLeading + tm.tmExternalLeading) * PANGO_SCALE; metrics->approximate_char_width = tm.tmAveCharWidth * PANGO_SCALE; coverage = pango_win32_font_get_coverage (font, language); diff --git a/utils/viewer-render.c b/utils/viewer-render.c index 51ba00fb..5a556cd8 100644 --- a/utils/viewer-render.c +++ b/utils/viewer-render.c @@ -52,6 +52,7 @@ int opt_width = -1; int opt_height = -1; int opt_indent = 0; int opt_spacing = 0; +double opt_line_spacing = 0.0; gboolean opt_justify = 0; int opt_runs = 1; PangoAlignment opt_align = PANGO_ALIGN_LEFT; @@ -126,6 +127,9 @@ make_layout(PangoContext *context, if (opt_spacing != 0) pango_layout_set_spacing (layout, (opt_spacing * opt_dpi * PANGO_SCALE + 36) / 72); + if (opt_line_spacing != 0.0) + pango_layout_set_line_spacing (layout, (float)opt_line_spacing); + align = opt_align; if (align != PANGO_ALIGN_CENTER && pango_context_get_base_dir (context) != PANGO_DIRECTION_LTR) { @@ -710,6 +714,8 @@ parse_options (int argc, char *argv[]) "Width in points to indent paragraphs", "points"}, {"spacing", 0, 0, G_OPTION_ARG_INT, &opt_spacing, "Spacing in points between lines", "points"}, + {"line-spacing", 0, 0, G_OPTION_ARG_DOUBLE, &opt_line_spacing, + "Spread factor for line height", "factor"}, {"justify", 0, 0, G_OPTION_ARG_NONE, &opt_justify, "Align paragraph lines to be justified", NULL}, {"language", 0, 0, G_OPTION_ARG_STRING, &opt_language, |