def __init__(self, x, y, context, cLine=None): """Container for line info, after text wrapping by context.""" self.x = units(x) self.y = units(y) self.runs = [] # List of BabelRunInfo instances. self.context = context # Just in case it is needed. # Optional native "context line" (e.g. DrawBot-->CTLine instance. # Flat-->the result of placedText.layout.runs() looping). self.cLine = cLine
def __init__(self, offset=None, blur=None, color=None): """Set he parameter of the Shadow instance. TODO: Make optional to use the z-position of an element really cast the shadow, defining both the offset (from light-source position) and blur from distance.""" self.offset = units(offset or (6, -6)) if blur is None: # In case not defined, attach to offset. blur = self.offset[0] self.blur = units(blur) self.color = makeColor(color or blackColor)
def _getValidSize(self, w, h): """Answer a valid size for FlatContext document and pages. Make default page size, similar to DrawBot.""" if w is None or w < 0: w = pt(1000) if h is None or h < 0: h = pt(1000) return units(w), units(h)
def setSize(self, w=None, h=None): """Optional default document size. If not None, overwriting the size of the open Sketch document. >>> context = SketchContext() >>> context.w is None and context.h is None True >>> context.setSize(w=300) >>> context.w 300pt """ self.w = units(w) self.h = units(h)
def _get_h(self): """Answer the height of the textBox. If self.style['h'] is None, then answer the vertical space that the text needs. >>> from pagebot.fonttoolbox.objects.font import findFont >>> from pagebot.document import Document >>> doc = Document(w=300, h=400, autoPages=1, padding=30) >>> page = doc[1] >>> font = findFont('Roboto-Regular') >>> style = dict(font=font.path, fontSize=14) >>> tb = TextBox('This is content', parent=page, style=style, w=100, h=220) >>> page[tb.eId].h 220pt """ """ TODO: Get the tests to work properly >>> tb.h = 220 >>> tb.h, tb.h == page[tb.eId].h (220, True) >>> tb.h = None >>> tb.h, tb.style['h'] is None (37.0, True) """ if self.style['h'] is None: # Elastic height h = self.getTextSize(w=self.w)[1] else: base = dict( base=self.parentH, em=self.em) # In case relative units, use this as base. h = units(self.css('h', 0), base=base) return h
def _set_h(self, h): # Overwrite style from here, unless self.style['elasticH'] is True if h is not None: # If None, then self.h is elastic defined by content h = units( h or DEFAULT_HEIGHT ) # Overwrite element local style from here, parent css becomes inaccessable. self.style['h'] = h
def __init__(self, offset=None, blur=None, color=None): """Set the parameter of the Shadow instance. TODO: Make optional to use the z-position of an element really cast the shadow, defining both the offset (from light-source position) and blur from distance. >>> shadow = Shadow() >>> shadow <Shadow offset=(6pt, -6pt) blur=6pt Color(r=0, g=0, b=0)> """ self.offset = units(offset or (6, -6)) if blur is None: # In case not defined, attach to offset. blur = self.offset[0] self.blur = units(blur) if color is None: self.color = blackColor else: self.color = makeColor(color)
def _get_h(self): """Answers the height of the Line element. >>> e = Line(h=100) >>> e.h 100pt >>> e = Line(h=0) >>> e.h 0pt """ base = dict(base=self.parentH, em=self.em) # In case relative units, use this as base. return units(self.css('h', 0), base=base)
def _get_h(self): u = None if not self._h: # Width is undefined iwpt = upt(self.iw) if self._w and iwpt: u = self.ih * upt(self._w / iwpt) # Width is lead, calculate height. else: u = self.ih # Undefined and without parent, answer original image width. else: base = dict(base=self.parentH, em=self.em) # In case relative units, use the right kind of base. u = units(self._h, base=base) # Height is lead and defined as not 0 or None. return u
def _get_w(self): """Answers the width of the Line element. >>> e = Line(w=100) >>> e.w 100pt >>> e = Line(w=0) >>> e.w 0pt """ base = dict(base=self.parentW, em=self.em) # In case relative units, use this as base. return units(self.css('w', 0), base=base)
def _get_w(self): """Get the intended width and calculate the new scale, validating the width to the image minimum width and the height to the image minimum height. If not self._h is defined, then the proportion is recalculated, depending on the ratio of the image.""" u = None if not self._w: # Width is undefined ihpt = upt(self.ih) if self._h and ihpt: u = self.iw * upt(self._h / ihpt) # Height is lead, calculate width. else: u = self.iw # Undefined and without parent, answer original image width. else: base = dict(base=self.parentW, em=self.em) # In case relative units, use the right kind of base. u = units(self._w, base=base) # Width is lead and defined as not 0 or None. return u
def _get_w(self): # Width """Property for self.w, holding the width of the textbox. >>> from pagebot.document import Document >>> doc = Document(w=300, h=400, autoPages=1, padding=30) >>> page = doc[1] >>> tb = TextBox(parent=page, w=125) >>> page[tb.eId].w 125pt >>> tb.w = 150 >>> tb.w, tb.w == page[tb.eId].w (150pt, True) """ base = dict(base=self.parentW, em=self.em) # In case relative units, use this as base. return units(self.css('w'), base=base)
def _get_w(self): # Width """Property answering the global (intended) width of the document as defined by self.rootStyle['w']. This may not represent the actual width of the document, which comes from the maximum width of all child pages together and if the current view is defined as spread. >>> doc = Document(name='TestDoc', w=100) >>> doc.w 100pt >>> doc.rootStyle['w'] = 200 >>> doc.w 200pt >>> doc.w = 300 >>> doc.w 300pt """ return units(self.rootStyle['w'])
def _get_d(self): # Depth """Property answering the global (intended) depth of the document as defined by self.rootStyle['d']. This may not represent the actual depth of the document, which comes from the maximum depth of all child pages together. >>> doc = Document(name='TestDoc', d=100) >>> doc.d 100pt >>> doc.rootStyle['d'] = 200 >>> doc.d 200pt >>> doc.d = 300 >>> doc.d 300pt """ return units(self.rootStyle['d']) # From self.style, don't inherit.
def _get_h(self): # Height """Property answering the global (intended) height of the document as defined by self.rootStyle['h']. This may not represent the actual height of the document, which comes from the maximum height of all child pages together. >>> doc = Document(name='TestDoc', h=100) >>> doc.h 100pt >>> doc.rootStyle['h'] = 200 >>> doc.h 200pt >>> doc.h = 300 >>> doc.h 300pt """ return units(self.rootStyle['h'])
def _get_pr(self): # Margin right """Padding right property. Interface is identical to Element.pr. >>> doc = Document(name='Testoc', pr=12) >>> doc.pr 12pt >>> doc.pr = 13 >>> doc.pr 13pt >>> doc.padding # Taking over default value of root style. (42pt, 13pt, 36pt, 42pt) >>> doc.padding3D # Taking over default value of root style. (42pt, 13pt, 36pt, 42pt, 0pt, 0pt) """ w = self.w base = dict(base=w, em=self.em) # In case relative units, use this as base. return units(self.rootStyle.get('pr', 0), base=base)
def _get_baselineGridStart(self): """Answers the baseline grid startf, as defined in the (parent) style. >>> from pagebot.elements.element import Element >>> e = Element() >>> # Undefined without style or parent style. >>> e.baselineGridStart is None True >>> e.baselineGridStart = 17 >>> e.baselineGridStart 17pt >>> e = Element(style=dict(baselineGridStart=15)) >>> e.baselineGridStart 15pt """ # In case relative units, use this as base for % #base = dict(base=self.parentH, em=self.em) return units(self.css('baselineGridStart'))#, base=base)
def _get_pl(self): # Padding left """Padding left property Interface is identical to Element.pl. >>> doc = Document(name='Testoc', pl=12) >>> doc.pl 12pt >>> doc.pl = 13 >>> doc.pl 13pt >>> doc.padding # Taking over default value of root style. (42pt, 36pt, 36pt, 13pt) >>> doc.padding3D # Taking over default value of root style. (42pt, 36pt, 36pt, 13pt, 0pt, 0pt) """ w = self.w base = dict(base=w, em=self.em) # In case relative units, use this as base. return units(self.rootStyle.get('pl'), base=base)
def _get_pzb(self): # Padding z-axis back """Padding padding z-front property. Interface is identical to Element.pzb. >>> doc = Document(name='Testoc', d=100, pzb=12) >>> doc.d, doc.pzb # Needs some depth > 1, for padding not to be clipped. (100pt, 12pt) >>> doc.pzb = 13 >>> doc.pzb 13pt >>> doc.padding # Taking over default value of root style. (42pt, 36pt, 36pt, 42pt) >>> doc.padding3D # Taking over default value of root style. (42pt, 36pt, 36pt, 42pt, 0pt, 13pt) """ d = self.d base = dict(base=self.d, em=self.em) # In case relative units, use this as base. return units(self.rootStyle.get('pzb', 0), base=base)
def _get_pb(self): # Padding bottom """Padding bottom property Interface is identical to Element.pb. >>> doc = Document(name='TestDoc', pb=12) >>> doc.pb 12pt >>> doc.pb = 13 >>> doc.pb 13pt >>> doc.padding # Taking over default value of root style. (42pt, 36pt, 13pt, 42pt) >>> doc.padding3D # Taking over default value of root style. (42pt, 36pt, 13pt, 42pt, 0pt, 0pt) """ h = self.h base = dict(base=h, em=self.em) # In case relative units, use this as base. return units(self.rootStyle.get('pb'), base=base)
def _get_fontSize(self): """Answers the current state of the fontSize. >>> from pagebot.toolbox.units import mm >>> from drawbotcontext import DrawBotContext >>> context = DrawBotContext() >>> style = dict(font='Verdana', fontSize=pt(85), leading=em(1.4)) >>> bs = context.newString('Example Text', style=style) >>> bs.fontSize 85pt >>> bs.fontSize = 96 # Auto-convert to points >>> bs.fontSize 96pt >>> bs.fontSize = mm(5) # Set at unit. >>> bs.fontSize 5mm >>> #bs.leading 1.4em """ return units(self.style.get('fontSize'))
def _get_y(self): """Answer the y position of self. >>> e = Element(y=100, h=400) >>> e.x, e.y, e.z (0pt, 100pt, 0pt) >>> e.y = 200 >>> e.x, e.y, e.z (0pt, 200pt, 0pt) >>> child = Element(y='40%', parent=e) >>> child.y, child.y.pt # 40% of 400 (40%, 160) >>> e.h = 500 >>> child.y, child.y.pt # 40% of 500 dynamic calculation (40%, 200) """ # Retrieve as Unit instance and adjust attributes to current settings. base = dict(base=self.parentH, em=self.em) # In case relative units, use this as base. return units(self.style.get('y'), base=base)
def _get_h(self): """Poperty for the self.h height value >>> from pagebot.toolbox.units import mm >>> from pagebot.document import Document >>> doc = Document(w=300, h=400, autoPages=1, padding=30) >>> page = doc[1] >>> e = Ruler(parent=page, h=3) >>> e.h, e.style['h'], e.style['strokeWidth'] (3pt, 3pt, 3pt) >>> e.h = 20 >>> e.h, e.style['h'], e.style['strokeWidth'] # Identical (20pt, 20pt, 20pt) >>> e.h = mm(3) >>> e.h, e.style['h'], e.style['strokeWidth'] # Identical (3mm, 3mm, 3mm) """ base = dict(base=self.parentH, em=self.em) # In case relative units, use this as base. return units(self.css('strokeWidth', 0), base=base)
def _get_pt(self): # Padding top """Padding top property Interface is identical to Element.pt. In this method "pt" is abbreviation of padding-top, not units point. >>> doc = Document(name='TestDoc', pt=12) >>> doc.pt 12pt >>> doc.pt = 13 >>> doc.pt 13pt >>> doc.padding # Taking over default value of root style. (13pt, 36pt, 36pt, 42pt) >>> doc.padding3D # Taking over default value of root style. (13pt, 36pt, 36pt, 42pt, 0pt, 0pt) """ h = self.h base = dict(base=h, em=self.em) # In case relative units, use this as base. return units(self.rootStyle.get('pt'), base=base)
def _get_baselineGrid(self): """Answers the baseline grid distance, as defined in the (parent) style. >>> from pagebot.toolbox.units import mm, p >>> from pagebot.elements.element import Element >>> e = Element() >>> # Undefined without style or parent style. >>> e.baselineGrid is None True >>> e.baselineGrid = 12 >>> e.baselineGrid 12pt >>> e.baselineGrid = mm(13.5) >>> e.baselineGrid 13.5mm >>> e = Element(style=dict(baselineGrid=14)) >>> e.baselineGrid 14pt """ # In case relative units, use this as base for % #base = dict(base=self.parentH, em=self.em) return units(self.css('baselineGrid'))#, base=base)
def _set_h(self, h): self._h = units( h or DEFAULT_HEIGHT ) # If self._w is set too, do disproportional sizing. Otherwise set to 0 or None.
def _set_w(self, w): self._w = units( w or DEFAULT_WIDTH ) # If self._h is set too, do disproportioan sizing. Otherwise set to 0 or None.
def node_img(self, node, e): """Process the image. adding the img tag or a new image element to the galley. The alt attribute can contain additional information for the Image element. Keep the Image element in self.currentImage, in case we need to add captions. If a "w=<number>" pattern is present in the alt-attribute, then use it as width measurement for creating a cached image. This way an author can control the required size from within the content. Markdown could use code such as ![MyImage w=450](images/myImage.jpg) If one or both if (w, h) are defined, then set the imageScale flag accordingly. >>> from pagebot.contexts.htmlcontext.htmlcontext import HtmlContext >>> from pagebot.toolbox.units import units >>> context = HtmlContext() >>> ts = Typesetter(context=context) >>> ts.IMAGE_CACHE_NOSCALE.findall('aaa bbb') [] >>> ts.IMAGE_CACHE_NOSCALE.findall('w=100 noscale') ['noscale'] >>> units(ts.IMAGE_CACHE_WIDTH.findall('w=100 noscale')) (100pt,) >>> units(ts.IMAGE_CACHE_WIDTH.findall('w=50% wi=800 noscale')) (50%,) >>> units(ts.IMAGE_CACHE_WIDTHI.findall('w=50% wi=800 noscale')) (800pt,) >>> ts.IMAGE_CACHE_SIZE.findall('w=50% contain') ['contain'] """ w = wi = ww = h = hi = hh = xAlign = yAlign = None # Values are optional set by alt content. cover = contain = initial = inherit = False path = node.attrib.get('src') doScale = not path.endswith('.' + FILETYPE_SVG) and not path.endswith( '.' + FILETYPE_GIF) alt = node.attrib.get('alt') cssSize = cssRepeat = None if alt: xAlign = (self.IMAGE_CACHE_XALIGN.findall(alt) or [None])[0] # x=center yAlign = (self.IMAGE_CACHE_YALIGN.findall(alt) or [None])[0] # y=top wi = units( self.IMAGE_CACHE_WIDTHI.findall(alt) or [None])[0] # wi=800, wi=100% Defines the scaled cache size hi = units(self.IMAGE_CACHE_HEIGHTI.findall(alt) or [None])[0] # hi=800 w = units(self.IMAGE_CACHE_WIDTH.findall(alt) or [None])[0] # w=800, w=100% h = units(self.IMAGE_CACHE_HEIGHT.findall(alt) or [None])[0] # h=800 doScale = doScale and not self.IMAGE_CACHE_NOSCALE.findall(alt) cssSize = (self.IMAGE_CACHE_SIZE.findall(alt) or [None])[0] cssRepeat = (self.IMAGE_CACHE_REPEAT.findall(alt) or [None])[0] # doScale = doScale or w is not None or h is not None proportional = not (w is not None and h is not None ) # Not proportional if both are defined. # auto Default value. The background image is displayed in its original size # (iw, ih) Sets the width and height of the scaled cached image file. # (w, h) Sets the width and height of the background image for CSS. # The first value sets the width, the second value sets the height. # If only one value is given, the second is set to "auto". Read about length units # w and h can be fixed units or pecentage. # A percentage sets the width and height of the background image in percent of the parent element. # The first value sets the width, the second value sets the height. # If only one value is given, the second is set to "auto" Play it » # cover Resize the background image to cover the entire container, # even if it has to stretch the image or cut a little bit off one of the edges Play it » # contain Resize the background image to make sure the image is fully visible Play it » # initial Sets this property to its default value. Read about initial Play it » # inherit Inherits this property from its parent element. Read about inherit if not cssSize in ('cover', 'contain', 'initial', 'inherit'): if h is not None and w is not None: cssSize = '%s %s' % (w, h) elif w is not None: cssSize = '%s auto' % w elif h is not None: cssSize = 'auto %s' % h else: cssSize = 'auto' self.currentImage = self.IMAGE_CLASS( path=path, parent=self.galley, scaleImage= doScale, # Scale the image if one or both (w, h) is defined. cssSize= cssSize, # Examples "auto 100%" "100% auto" "cover" "contain" "initial" "inherit" cssRepeat=cssRepeat, xAlign=xAlign, yAlign=yAlign, w=wi or self.maxImageWidth, h=hi, # To alter the scaled image file from source level. alt=alt, proportional=proportional, maxImageWidth=self.maxImageWidth, index=node.attrib.get('index', 0), context=self.context)
def _set_tailIndent(self, tailIndent): tailIndent = units(tailIndent) if self._bs: self.bs.tailIndent = tailIndent self.style['tailIndent'] = tailIndent
def _set_indent(self, indent): indent = units(indent) if self._bs: self.bs.indent = indent self.style['indent'] = indent