M .golden/czechHelloParagraph/golden => .golden/czechHelloParagraph/golden +2 -2
@@ 1,5 1,5 @@
ParagraphLayout {paragraphRect = Rect {x_origin = 0, y_origin = 0, x_size = 5274, y_size = 0}, spanLayouts = [
- SpanLayout [(Rect {x_origin = 0, y_origin = 0, x_size = 5274, y_size = 0},
+ SpanLayout [Fragment {fragmentRect = Rect {x_origin = 0, y_origin = 0, x_size = 5274, y_size = 0}, fragmentPen = (0,0), fragmentGlyphs =
[(GlyphInfo {codepoint = 36, cluster = 0, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 663, y_advance = 0, x_offset = 0, y_offset = 0}),
(GlyphInfo {codepoint = 75, cluster = 1, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 571, y_advance = 0, x_offset = 0, y_offset = 0}),
(GlyphInfo {codepoint = 82, cluster = 2, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 590, y_advance = 0, x_offset = 0, y_offset = 0}),
@@ 12,5 12,5 @@ ParagraphLayout {paragraphRect = Rect {x_origin = 0, y_origin = 0, x_size = 5274
(GlyphInfo {codepoint = 87, cluster = 10, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 392, y_advance = 0, x_offset = 0, y_offset = 0}),
(GlyphInfo {codepoint = 72, cluster = 11, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 559, y_advance = 0, x_offset = 0, y_offset = 0}),
(GlyphInfo {codepoint = 4, cluster = 12, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 276, y_advance = 0, x_offset = 0, y_offset = 0})]
- )]
+ }]
]}
M .golden/mixedLanguageLTRParagraph/golden => .golden/mixedLanguageLTRParagraph/golden +4 -4
@@ 1,5 1,5 @@
ParagraphLayout {paragraphRect = Rect {x_origin = 0, y_origin = 0, x_size = 6113, y_size = 0}, spanLayouts = [
- SpanLayout [(Rect {x_origin = 0, y_origin = 0, x_size = 4837, y_size = 0},
+ SpanLayout [Fragment {fragmentRect = Rect {x_origin = 0, y_origin = 0, x_size = 4837, y_size = 0}, fragmentPen = (0,0), fragmentGlyphs =
[(GlyphInfo {codepoint = 77, cluster = 4, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 253, y_advance = 0, x_offset = 0, y_offset = 0}),
(GlyphInfo {codepoint = 86, cluster = 5, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 446, y_advance = 0, x_offset = 0, y_offset = 0}),
(GlyphInfo {codepoint = 72, cluster = 6, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 559, y_advance = 0, x_offset = 0, y_offset = 0}),
@@ 11,10 11,10 @@ ParagraphLayout {paragraphRect = Rect {x_origin = 0, y_origin = 0, x_size = 6113
(GlyphInfo {codepoint = 92, cluster = 12, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 497, y_advance = 0, x_offset = 0, y_offset = 0}),
(GlyphInfo {codepoint = 15, cluster = 13, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 246, y_advance = 0, x_offset = 0, y_offset = 0}),
(GlyphInfo {codepoint = 3, cluster = 14, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 231, y_advance = 0, x_offset = 0, y_offset = 0})]
- )],
- SpanLayout [(Rect {x_origin = 4837, y_origin = 0, x_size = 1276, y_size = 0},
+ }],
+ SpanLayout [Fragment {fragmentRect = Rect {x_origin = 4837, y_origin = 0, x_size = 1276, y_size = 0}, fragmentPen = (0,0), fragmentGlyphs =
[(GlyphInfo {codepoint = 0, cluster = 15, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 500, y_advance = 0, x_offset = 0, y_offset = 0}),
(GlyphInfo {codepoint = 0, cluster = 18, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 500, y_advance = 0, x_offset = 0, y_offset = 0}),
(GlyphInfo {codepoint = 4, cluster = 21, unsafeToBreak = False, unsafeToConcat = False, safeToInsertTatweel = False},GlyphPos {x_advance = 276, y_advance = 0, x_offset = 0, y_offset = 0})]
- )]
+ }]
]}
M balkon.cabal => balkon.cabal +1 -0
@@ 97,6 97,7 @@ library
-- Modules exported by the library.
exposed-modules:
Data.Text.ParagraphLayout,
+ Data.Text.ParagraphLayout.Fragment,
Data.Text.ParagraphLayout.Plain,
Data.Text.ParagraphLayout.Rect,
Data.Text.ParagraphLayout.ResolvedSpan,
A src/Data/Text/ParagraphLayout/Fragment.hs => src/Data/Text/ParagraphLayout/Fragment.hs +39 -0
@@ 0,0 1,39 @@
+module Data.Text.ParagraphLayout.Fragment (Fragment(..))
+where
+
+import Data.Int (Int32)
+import Data.Text.Glyphize (GlyphInfo, GlyphPos)
+
+import Data.Text.ParagraphLayout.Rect
+
+-- | Box fragment or fragment (CSS3), except that continuous text even within
+-- one line can be split into multiple fragments because of spans or changes in
+-- script.
+data Fragment = Fragment
+ { fragmentRect :: Rect Int32
+ -- ^ Physical position of the fragment within the paragraph, calculated
+ -- using all glyph advances in this fragment and the calculated line height.
+ --
+ -- This is the space that the glyphs "take up" and is probably what you
+ -- want to use for detecting position-based events such as mouse clicks.
+ --
+ -- Beware that actual glyphs will not be drawn exactly to the borders of
+ -- this rectangle -- they may be offset inwards and they can also extend
+ -- outwards!
+ --
+ -- These are not the typographic bounding boxes that you use for determining
+ -- the area to draw on -- you need FreeType or a similar library for that.
+ --
+ -- The origin coordinates are relative to the paragraph.
+ --
+ -- The sizes can be positive or negative, depending on the text direction.
+ --
+ -- X coordinates increase from left to right.
+ -- Y coordinates increase from bottom to top.
+ , fragmentPen :: (Int32, Int32)
+ -- ^ Coordinates of the initial pen position, from which the first glyph
+ -- should be drawn. That glyph's `x_advance` or `y_advance` are then used
+ -- to move the pen position for the next glyph.
+ , fragmentGlyphs :: [(GlyphInfo, GlyphPos)]
+ }
+ deriving (Eq, Read, Show)
M src/Data/Text/ParagraphLayout/Plain.hs => src/Data/Text/ParagraphLayout/Plain.hs +5 -33
@@ 28,7 28,6 @@ import Data.Text.Glyphize
(Buffer(..)
,ContentType(ContentTypeUnicode)
,Font
- ,GlyphInfo
,GlyphPos(x_advance, y_advance)
,defaultBuffer
,shape
@@ 36,6 35,7 @@ import Data.Text.Glyphize
import Data.Text.Internal (Text(Text))
import qualified Data.Text.Lazy as Lazy
+import Data.Text.ParagraphLayout.Fragment
import Data.Text.ParagraphLayout.Rect
import qualified Data.Text.ParagraphLayout.ResolvedSpan as RS
import Data.Text.ParagraphLayout.Run
@@ 91,36 91,6 @@ data ParagraphLayout = ParagraphLayout
data SpanLayout = SpanLayout [Fragment]
deriving (Eq, Read, Show)
--- | Box fragment or fragment (CSS3), except that continuous text even within
--- one line can be split into multiple fragments because of spans or changes in
--- script.
-type Fragment =
- ( Rect Int32
- -- ^ Physical position of the fragment within the paragraph, calculated
- -- using all glyph advances in this fragment and the calculated line height.
- --
- -- This is the space that the glyphs "take up" and is probably what you
- -- want to use for detecting position-based events such as mouse clicks.
- --
- -- Beware that actual glyphs will not be drawn exactly to the borders of
- -- this rectangle -- they may be offset inwards and they can also extend
- -- outwards!
- --
- -- These are not the typographic bounding boxes that you use for determining
- -- the area to draw on -- you need FreeType or a similar library for that.
- --
- -- The origin coordinates are relative to the paragraph.
- --
- -- The sizes can be positive or negative, depending on the text direction.
- --
- -- X coordinates increase from left to right.
- -- Y coordinates increase from bottom to top.
- , [(GlyphInfo, GlyphPos)]
- )
-
-fragmentRect :: Fragment -> Rect Int32
-fragmentRect = fst
-
spanRects :: SpanLayout -> [Rect Int32]
spanRects (SpanLayout frags) = map fragmentRect frags
@@ 157,8 127,9 @@ layoutPlain paragraph = ParagraphLayout pRect arrangedLayouts
layoutSpan :: RS.ResolvedSpan -> SpanLayout
layoutSpan rs = SpanLayout (map layoutRun $ spanToRuns rs)
+-- TODO: Calculate line height and pen position.
layoutRun :: Run -> Fragment
-layoutRun run = (rect, glyphs)
+layoutRun run = Fragment rect (0, 0) glyphs
where
rs = runOriginalSpan run
rect = containGlyphs $ map snd $ glyphs
@@ 219,7 190,8 @@ arrangeFragmentsH currentX frags = mapAccumL arrangeFragmentH currentX frags
-- | Set the horizontal offset of the given box
-- and return the x coordinate of its other side for continuation.
arrangeFragmentH :: Int32 -> Fragment -> (Int32, Fragment)
-arrangeFragmentH currentX (rect, glyphs) = (nextX, (newRect, glyphs))
+arrangeFragmentH currentX frag = (nextX, frag { fragmentRect = newRect })
where
+ rect = fragmentRect frag
nextX = currentX + x_size rect
newRect = rect { x_origin = currentX }
M test/Data/Text/ParagraphLayout/PlainSpec.hs => test/Data/Text/ParagraphLayout/PlainSpec.hs +12 -6
@@ 7,6 7,7 @@ import Test.Hspec
import Test.Hspec.Golden
import System.FilePath ((</>))
import Data.Text.ParagraphLayout.FontLoader
+import Data.Text.ParagraphLayout.Fragment
import Data.Text.ParagraphLayout.ParagraphData
import Data.Text.ParagraphLayout.Plain
@@ 23,23 24,28 @@ prettyShow (ParagraphLayout pr sls) = showParagraphLayout where
, newline
]
showSpanLayouts = concat $ intersperse commaNewline $ map showSpanLayout sls
- showSpanLayout (SpanLayout boxes) = concat
+ showSpanLayout (SpanLayout frags) = concat
[ indent1
, "SpanLayout ["
- , concat $ map showBox boxes
+ , concat $ map showFrag frags
, "]"
]
- showBox (r, glyphs) = concat
- [ "("
+ showFrag (Fragment r pen glyphs) = concat
+ [ "Fragment {fragmentRect = "
, show r
- , commaNewline
+ , ", "
+ , "fragmentPen = "
+ , show pen
+ , ", "
+ , "fragmentGlyphs ="
+ , newline
, indent2
, "["
, showGlyphs glyphs
, "]"
, newline
, indent1
- , ")"
+ , "}"
]
showGlyphs = concat . intersperse (commaNewline ++ indent2) . map show
indent1 = " "